]> git.sur5r.net Git - u-boot/blobdiff - common/init/board_init.c
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot] / common / init / board_init.c
index 1c6126d8ce55a08c85f8e0d576672fdf7f16f8bf..526fee35ff679876aa9a14e6bdf8be674e93c69d 100644 (file)
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Code shared between SPL and U-Boot proper
  *
  * Copyright (c) 2015 Google, Inc
  * Written by Simon Glass <sjg@chromium.org>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* Unfortunately x86 or ARM can't compile this code as gd cannot be assigned */
+#if !defined(CONFIG_X86) && !defined(CONFIG_ARM)
+__weak void arch_setup_gd(struct global_data *gd_ptr)
+{
+       gd = gd_ptr;
+}
+#endif /* !CONFIG_X86 && !CONFIG_ARM */
+
 /*
- * It isn't trivial to figure out whether memcpy() exists. The arch-specific
- * memcpy() is not normally available in SPL due to code size.
+ * Allocate reserved space for use as 'globals' from 'top' address and
+ * return 'bottom' address of allocated space
+ *
+ * Notes:
+ *
+ * Actual reservation cannot be done from within this function as
+ * it requires altering the C stack pointer, so this will be done by
+ * the caller upon return from this function.
+ *
+ * IMPORTANT:
+ *
+ * Alignment constraints may differ for each 'chunk' allocated. For now:
+ *
+ * - GD is aligned down on a 16-byte boundary
+ *
+ *  - the early malloc arena is not aligned, therefore it follows the stack
+ *   alignment constraint of the architecture for which we are bulding.
+ *
+ *  - GD is allocated last, so that the return value of this functions is
+ *   both the bottom of the reserved area and the address of GD, should
+ *   the calling context need it.
  */
-#if !defined(CONFIG_SPL_BUILD) || \
-               (defined(CONFIG_SPL_LIBGENERIC_SUPPORT) && \
-               !defined(CONFIG_USE_ARCH_MEMSET))
-#define _USE_MEMCPY
-#endif
 
-/* Unfortunately x86 can't compile this code as gd cannot be assigned */
-#ifndef CONFIG_X86
-__weak void arch_setup_gd(struct global_data *gd_ptr)
+ulong board_init_f_alloc_reserve(ulong top)
 {
-       gd = gd_ptr;
+       /* Reserve early malloc arena */
+#if CONFIG_VAL(SYS_MALLOC_F_LEN)
+       top -= CONFIG_VAL(SYS_MALLOC_F_LEN);
+#endif
+       /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
+       top = rounddown(top-sizeof(struct global_data), 16);
+
+       return top;
 }
-#endif /* !CONFIG_X86 */
 
-ulong board_init_f_mem(ulong top)
+/*
+ * Initialize reserved space (which has been safely allocated on the C
+ * stack from the C runtime environment handling code).
+ *
+ * Notes:
+ *
+ * Actual reservation was done by the caller; the locations from base
+ * to base+size-1 (where 'size' is the value returned by the allocation
+ * function above) can be accessed freely without risk of corrupting the
+ * C runtime environment.
+ *
+ * IMPORTANT:
+ *
+ * Upon return from the allocation function above, on some architectures
+ * the caller will set gd to the lowest reserved location. Therefore, in
+ * this initialization function, the global data MUST be placed at base.
+ *
+ * ALSO IMPORTANT:
+ *
+ * On some architectures, gd will already be good when entering this
+ * function. On others, it will only be good once arch_setup_gd() returns.
+ * Therefore, global data accesses must be done:
+ *
+ * - through gd_ptr if before the call to arch_setup_gd();
+ *
+ * - through gd once arch_setup_gd() has been called.
+ *
+ * Do not use 'gd->' until arch_setup_gd() has been called!
+ *
+ * IMPORTANT TOO:
+ *
+ * Initialization for each "chunk" (GD, early malloc arena...) ends with
+ * an incrementation line of the form 'base += <some size>'. The last of
+ * these incrementations seems useless, as base will not be used any
+ * more after this incrementation; but if/when a new "chunk" is appended,
+ * this increment will be essential as it will give base right value for
+ * this new chunk (which will have to end with its own incrementation
+ * statement). Besides, the compiler's optimizer will silently detect
+ * and remove the last base incrementation, therefore leaving that last
+ * (seemingly useless) incrementation causes no code increase.
+ */
+
+void board_init_f_init_reserve(ulong base)
 {
        struct global_data *gd_ptr;
-#ifndef _USE_MEMCPY
-       int *ptr;
-#endif
 
-       /* Leave space for the stack we are running with now */
-       top -= 0x40;
+       /*
+        * clear GD entirely and set it up.
+        * Use gd_ptr, as gd may not be properly set yet.
+        */
 
-       top -= sizeof(struct global_data);
-       top = ALIGN(top, 16);
-       gd_ptr = (struct global_data *)top;
-#ifdef _USE_MEMCPY
+       gd_ptr = (struct global_data *)base;
+       /* zero the area */
        memset(gd_ptr, '\0', sizeof(*gd));
-#else
-       for (ptr = (int *)gd_ptr; ptr < (int *)(gd_ptr + 1); )
-               *ptr++ = 0;
-#endif
+       /* set GD unless architecture did it already */
+#if !defined(CONFIG_ARM)
        arch_setup_gd(gd_ptr);
-
-#if defined(CONFIG_SYS_MALLOC_F)
-       top -= CONFIG_SYS_MALLOC_F_LEN;
-       gd->malloc_base = top;
 #endif
+       /* next alloc will be higher by one GD plus 16-byte alignment */
+       base += roundup(sizeof(struct global_data), 16);
 
-       return top;
+       /*
+        * record early malloc arena start.
+        * Use gd as it is now properly set for all architectures.
+        */
+
+#if CONFIG_VAL(SYS_MALLOC_F_LEN)
+       /* go down one 'early malloc arena' */
+       gd->malloc_base = base;
+       /* next alloc will be higher by one 'early malloc arena' size */
+       base += CONFIG_VAL(SYS_MALLOC_F_LEN);
+#endif
 }
+
+/*
+ * Board-specific Platform code can reimplement show_boot_progress () if needed
+ */
+__weak void show_boot_progress(int val) {}