Refactor arm-uboot code to make it genereic.
authorVladimir Serbinenko <phcoder@gmail.com>
Mon, 8 May 2017 15:47:57 +0000 (17:47 +0200)
committerVladimir Serbinenko <phcoder@gmail.com>
Mon, 8 May 2017 15:47:57 +0000 (17:47 +0200)
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
grub-core/kern/arm/startup.S [moved from grub-core/kern/arm/uboot/startup.S with 77% similarity]
grub-core/kern/arm/uboot/init.c [new file with mode: 0644]
grub-core/kern/arm/uboot/uboot.S [new file with mode: 0644]
grub-core/kern/uboot/init.c
grub-core/kern/uboot/uboot.c
include/grub/arm/startup.h [new file with mode: 0644]

index 8dcd0e5..fb59a7b 100644 (file)
@@ -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;
similarity index 77%
rename from grub-core/kern/arm/uboot/startup.S
rename to grub-core/kern/arm/startup.S
index 5efaae1..640837c 100644 (file)
@@ -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       @ r8
+       .long   0       @ r9
        .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       @ sp
        .long   0       @ lr
-       .long   0       @ r9
-
-VARIABLE(grub_uboot_syscall_ptr)
-       .long   0       @
-
-       END
+entry_state:
diff --git a/grub-core/kern/arm/uboot/init.c b/grub-core/kern/arm/uboot/init.c
new file mode 100644 (file)
index 0000000..2a6aa3f
--- /dev/null
@@ -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;
+}
diff --git a/grub-core/kern/arm/uboot/uboot.S b/grub-core/kern/arm/uboot/uboot.S
new file mode 100644 (file)
index 0000000..d128775
--- /dev/null
@@ -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
index 5dcc106..3e33864 100644 (file)
 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)
 {
index 6800a4b..cf0168e 100644 (file)
  * 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 (file)
index 0000000..9afb6c5
--- /dev/null
@@ -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