Refactor arm-uboot code to make it genereic.

arm-coreboot startup code can be very similar to arm-uboot but current code has
U-Boot specific references. So split U-Boot part from generic part.
This commit is contained in:
Vladimir Serbinenko 2017-05-08 17:47:57 +02:00
parent a35ac85430
commit d08c968514
7 changed files with 170 additions and 108 deletions

View file

@ -105,7 +105,7 @@ kernel = {
mips_startup = kern/mips/startup.S; mips_startup = kern/mips/startup.S;
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
arm_uboot_startup = kern/arm/uboot/startup.S; arm_uboot_startup = kern/arm/startup.S;
arm_efi_startup = kern/arm/efi/startup.S; arm_efi_startup = kern/arm/efi/startup.S;
arm64_efi_startup = kern/arm64/efi/startup.S; arm64_efi_startup = kern/arm64/efi/startup.S;
@ -149,6 +149,8 @@ kernel = {
uboot = kern/uboot/init.c; uboot = kern/uboot/init.c;
uboot = kern/uboot/hw.c; uboot = kern/uboot/hw.c;
uboot = term/uboot/console.c; uboot = term/uboot/console.c;
arm_uboot = kern/arm/uboot/init.c;
arm_uboot = kern/arm/uboot/uboot.S;
terminfoinkernel = term/terminfo.c; terminfoinkernel = term/terminfo.c;
terminfoinkernel = term/tparm.c; terminfoinkernel = term/tparm.c;

View file

@ -86,7 +86,7 @@ FUNCTION(codestart)
@ Stack pointer used as start address for signature probing @ Stack pointer used as start address for signature probing
mov r12, sp mov r12, sp
adr sp, entry_state adr sp, entry_state
push {r1-r12,lr} @ store U-Boot context (sp in r12) push {r0-r12,lr} @ store U-Boot context (sp in r12)
adr r1, _start adr r1, _start
ldr r0, bss_start_ptr @ src ldr r0, bss_start_ptr @ src
@ -153,69 +153,21 @@ reloc_done:
b EXT_C(grub_main) b EXT_C(grub_main)
/*
* uboot_syscall():
* This function is effectively a veneer, so it cannot
* modify the stack or corrupt any registers other than
* r12 (ip). Furthermore it needs to restore r8 for
* U-Boot (Global Data Pointer) and preserve it for Grub.
*/
FUNCTION(grub_uboot_syscall)
str r8, transition_space
str lr, transition_space + 4
str r9, transition_space + 8
ldr r8, gd_backup
ldr r9, gd_backup + 4
bl do_syscall
ldr r8, transition_space
ldr lr, transition_space + 4
ldr r9, transition_space + 8
bx lr
do_syscall:
ldr ip, grub_uboot_syscall_ptr
bx ip
FUNCTION(grub_uboot_return)
adr sp, entry_state_end
pop {r4-r12, lr}
mov sp, r12
bx lr
.align 3 .align 3
@ U-boot context stack space @ U-boot/coreboot context stack space
entry_state_end: VARIABLE(grub_arm_saved_registers)
VARIABLE(grub_uboot_machine_type) .long 0 @ r0
.long 0 @ r1 .long 0 @ r1
VARIABLE(grub_uboot_boot_data)
.long 0 @ r2 .long 0 @ r2
.long 0 @ r3 .long 0 @ r3
.long 0 @ r4 .long 0 @ r4
.long 0 @ r5 .long 0 @ r5
.long 0 @ r6 .long 0 @ r6
.long 0 @ r7 .long 0 @ r7
gd_backup: .long 0 @ r8
.long 0 @ r8 - U-Boot global data pointer up to 2013-09-21 .long 0 @ r9
.long 0 @ r9 - U-Boot global data pointer 2013-09-21 onwards
.long 0 @ r10 .long 0 @ r10
.long 0 @ r11 .long 0 @ r11
VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer - .long 0 @ sp
.long 0 @ also API signature address hint.
.long 0 @ lr .long 0 @ lr
entry_state: @ backup for U-Boot context entry_state:
@ GRUB context stack space
transition_space:
.long 0 @ r8
.long 0 @ lr
.long 0 @ r9
VARIABLE(grub_uboot_syscall_ptr)
.long 0 @
END

View file

@ -0,0 +1,70 @@
/* init.c - generic U-Boot initialization and finalization */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/uboot/uboot.h>
#include <grub/arm/startup.h>
#include <grub/uboot/api_public.h>
extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
grub_uint32_t
grub_uboot_get_machine_type (void)
{
return grub_arm_saved_registers.r[1];
}
grub_addr_t
grub_uboot_get_boot_data (void)
{
return grub_arm_saved_registers.r[2];
}
int
grub_uboot_api_init (void)
{
struct api_signature *start, *end;
struct api_signature *p;
grub_addr_t grub_uboot_search_hint = grub_arm_saved_registers.sp;
if (grub_uboot_search_hint)
{
/* Extended search range to work around Trim Slice U-Boot issue */
start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff)
- 0x00500000);
end =
(struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
API_SIG_MAGLEN + 0x00500000);
}
else
{
start = 0;
end = (struct api_signature *) (256 * 1024 * 1024);
}
/* Structure alignment is (at least) 8 bytes */
for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
{
if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
{
grub_uboot_syscall_ptr = p->syscall;
return p->version;
}
}
return 0;
}

View file

@ -0,0 +1,73 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/offsets.h>
#include <grub/symbol.h>
#include <grub/machine/kernel.h>
/*
* uboot_syscall():
* This function is effectively a veneer, so it cannot
* modify the stack or corrupt any registers other than
* r12 (ip). Furthermore it needs to restore r8 for
* U-Boot (Global Data Pointer) and preserve it for Grub.
*/
FUNCTION(grub_uboot_syscall)
str r8, transition_space
str lr, transition_space + 4
str r9, transition_space + 8
ldr ip, saved_registers_ptr
ldr r8, [ip, #4 * 8]
ldr r9, [ip, #4 * 9]
bl do_syscall
ldr r8, transition_space
ldr lr, transition_space + 4
ldr r9, transition_space + 8
bx lr
do_syscall:
ldr ip, grub_uboot_syscall_ptr
bx ip
FUNCTION(grub_uboot_return)
ldr ip, saved_registers_ptr
ldr sp, [ip, #4 * 4]
pop {r4-r12, lr}
mov sp, r12
bx lr
.align 3
@ GRUB context stack space
transition_space:
.long 0 @ r8
.long 0 @ lr
.long 0 @ r9
saved_registers_ptr:
.long EXT_C(grub_arm_saved_registers)
VARIABLE(grub_uboot_syscall_ptr)
.long 0 @
END

View file

@ -36,30 +36,14 @@
extern char __bss_start[]; extern char __bss_start[];
extern char _end[]; extern char _end[];
extern grub_size_t grub_total_module_size; extern grub_size_t grub_total_module_size;
extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
static unsigned long timer_start; static unsigned long timer_start;
extern grub_uint32_t grub_uboot_machine_type;
extern grub_addr_t grub_uboot_boot_data;
void void
grub_exit (void) grub_exit (void)
{ {
grub_uboot_return (0); grub_uboot_return (0);
} }
grub_uint32_t
grub_uboot_get_machine_type (void)
{
return grub_uboot_machine_type;
}
grub_addr_t
grub_uboot_get_boot_data (void)
{
return grub_uboot_boot_data;
}
static grub_uint64_t static grub_uint64_t
uboot_timer_ms (void) uboot_timer_ms (void)
{ {

View file

@ -39,48 +39,13 @@
* returns: 0 if the call not found, 1 if serviced * returns: 0 if the call not found, 1 if serviced
*/ */
extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
extern int grub_uboot_syscall (int, int *, ...); extern int grub_uboot_syscall (int, int *, ...);
extern grub_addr_t grub_uboot_search_hint;
static struct sys_info uboot_sys_info; static struct sys_info uboot_sys_info;
static struct mem_region uboot_mem_info[5]; static struct mem_region uboot_mem_info[5];
static struct device_info * devices; static struct device_info * devices;
static int num_devices; static int num_devices;
int
grub_uboot_api_init (void)
{
struct api_signature *start, *end;
struct api_signature *p;
if (grub_uboot_search_hint)
{
/* Extended search range to work around Trim Slice U-Boot issue */
start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff)
- 0x00500000);
end =
(struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
API_SIG_MAGLEN + 0x00500000);
}
else
{
start = 0;
end = (struct api_signature *) (256 * 1024 * 1024);
}
/* Structure alignment is (at least) 8 bytes */
for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
{
if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
{
grub_uboot_syscall_ptr = p->syscall;
return p->version;
}
}
return 0;
}
/* /*
* All functions below are wrappers around the grub_uboot_syscall() function * All functions below are wrappers around the grub_uboot_syscall() function

View file

@ -0,0 +1,16 @@
#ifndef GRUB_STARTUP_CPU_HEADER
#define GRUB_STARTUP_CPU_HEADER
struct grub_arm_startup_registers
{
/* registers 0-11 */
/* for U-boot r[1] is machine type */
/* for U-boot r[2] is boot data */
grub_uint32_t r[12];
grub_uint32_t sp;
grub_uint32_t lr;
};
extern struct grub_arm_startup_registers grub_arm_saved_registers;
#endif