From d08c9685149e7788001ac9a209baa1d84c3628e0 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 8 May 2017 17:47:57 +0200 Subject: [PATCH 015/251] 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. --- grub-core/Makefile.core.def | 4 +- grub-core/kern/arm/uboot/init.c | 70 ++++++++++++++++++++++++++++++ grub-core/kern/uboot/init.c | 16 ------- grub-core/kern/uboot/uboot.c | 35 --------------- include/grub/arm/startup.h | 16 +++++++ grub-core/kern/arm/{uboot => }/startup.S | 66 ++++------------------------- grub-core/kern/arm/uboot/uboot.S | 73 ++++++++++++++++++++++++++++++++ 7 files changed, 171 insertions(+), 109 deletions(-) create mode 100644 grub-core/kern/arm/uboot/init.c create mode 100644 include/grub/arm/startup.h rename grub-core/kern/arm/{uboot => }/startup.S (77%) create mode 100644 grub-core/kern/arm/uboot/uboot.S diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 8dcd0e5a998..fb59a7b1d6a 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -105,7 +105,7 @@ kernel = { mips_startup = kern/mips/startup.S; sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.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; arm64_efi_startup = kern/arm64/efi/startup.S; @@ -149,6 +149,8 @@ kernel = { uboot = kern/uboot/init.c; uboot = kern/uboot/hw.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/tparm.c; diff --git a/grub-core/kern/arm/uboot/init.c b/grub-core/kern/arm/uboot/init.c new file mode 100644 index 00000000000..2a6aa3fdd3d --- /dev/null +++ b/grub-core/kern/arm/uboot/init.c @@ -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 . + */ + +#include +#include +#include + +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; +} diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c index 5dcc106ed9b..3e338645c57 100644 --- a/grub-core/kern/uboot/init.c +++ b/grub-core/kern/uboot/init.c @@ -36,30 +36,14 @@ extern char __bss_start[]; extern char _end[]; extern grub_size_t grub_total_module_size; -extern int (*grub_uboot_syscall_ptr) (int, int *, ...); static unsigned long timer_start; -extern grub_uint32_t grub_uboot_machine_type; -extern grub_addr_t grub_uboot_boot_data; - void grub_exit (void) { 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 uboot_timer_ms (void) { diff --git a/grub-core/kern/uboot/uboot.c b/grub-core/kern/uboot/uboot.c index 6800a4beb1c..cf0168e62dd 100644 --- a/grub-core/kern/uboot/uboot.c +++ b/grub-core/kern/uboot/uboot.c @@ -39,48 +39,13 @@ * 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 grub_addr_t grub_uboot_search_hint; static struct sys_info uboot_sys_info; static struct mem_region uboot_mem_info[5]; static struct device_info * 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 diff --git a/include/grub/arm/startup.h b/include/grub/arm/startup.h new file mode 100644 index 00000000000..9afb6c57c0b --- /dev/null +++ b/include/grub/arm/startup.h @@ -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 diff --git a/grub-core/kern/arm/uboot/startup.S b/grub-core/kern/arm/startup.S similarity index 77% rename from grub-core/kern/arm/uboot/startup.S rename to grub-core/kern/arm/startup.S index 5efaae16e83..640837cba51 100644 --- a/grub-core/kern/arm/uboot/startup.S +++ b/grub-core/kern/arm/startup.S @@ -86,7 +86,7 @@ FUNCTION(codestart) @ Stack pointer used as start address for signature probing mov r12, sp 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 ldr r0, bss_start_ptr @ src @@ -153,69 +153,21 @@ reloc_done: 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 -@ U-boot context stack space -entry_state_end: -VARIABLE(grub_uboot_machine_type) +@ U-boot/coreboot context stack space +VARIABLE(grub_arm_saved_registers) + .long 0 @ r0 .long 0 @ r1 -VARIABLE(grub_uboot_boot_data) .long 0 @ r2 .long 0 @ r3 .long 0 @ r4 .long 0 @ r5 .long 0 @ r6 .long 0 @ r7 -gd_backup: - .long 0 @ r8 - U-Boot global data pointer up to 2013-09-21 - .long 0 @ r9 - U-Boot global data pointer 2013-09-21 onwards - .long 0 @ r10 - .long 0 @ r11 -VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer - - .long 0 @ also API signature address hint. - .long 0 @ lr -entry_state: @ backup for U-Boot context - -@ GRUB context stack space -transition_space: .long 0 @ r8 - .long 0 @ lr .long 0 @ r9 - -VARIABLE(grub_uboot_syscall_ptr) - .long 0 @ - - END + .long 0 @ r10 + .long 0 @ r11 + .long 0 @ sp + .long 0 @ lr +entry_state: diff --git a/grub-core/kern/arm/uboot/uboot.S b/grub-core/kern/arm/uboot/uboot.S new file mode 100644 index 00000000000..d128775f19e --- /dev/null +++ b/grub-core/kern/arm/uboot/uboot.S @@ -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 . + */ + +#include +#include +#include + + /* + * 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 -- 2.17.1