[U-Boot] [PATCH 14/25] x86: Support Intel FSP initialization path in start.S

Per Intel FSP architecture specification, FSP provides 3 routines for bootloader to call. The first one is the TempRamInit (aka Cache-As-Ram initialization) and the second one is the FspInit which does the memory bring up (like MRC for other x86 targets) and chipset initialization. Those two routines have to be called before U-Boot jumping to board_init_f in start.S.
The FspInit() will return several memory blocks called Hand Off Blocks (HOBs) whose format is described in Platform Initialization (PI) specification (part of the UEFI specication) to the bootloader. Save this HOB address to the U-Boot global data for later use.
Signed-off-by: Bin Meng bmeng.cn@gmail.com --- arch/x86/cpu/start.S | 37 +++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/global_data.h | 3 +++ arch/x86/lib/asm-offsets.c | 3 +++ 3 files changed, 43 insertions(+)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index f9662fb..b4a69d2 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -75,6 +75,35 @@ early_board_init_ret: jmp car_init .globl car_init_ret car_init_ret: +#ifdef CONFIG_HAVE_FSP + /* + * The FSP TempRamInit initializes the ecx and edx registers to + * point to a temporary but writable memory range (Cache-As-RAM). + * ecx: the start of this temporary memory range, + * edx: the end of this range. + */ + + /* stack grows down from top of CAR */ + movl %edx, %esp + + movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax + xorl %edx, %edx + xorl %ecx, %ecx + call FspInitWrapper + +.global fsp_init_done +fsp_init_done: + /* + * We come here from FspInit with eax pointing to the HOB list. + * Save eax to esi temporarily. + */ + movl %eax, %esi + /* + * Re-initialize the ebp (BIST) to zero, as we already reach here + * which means we passed BIST testing before. + */ + xorl %ebp, %ebp +#else /* * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, * or fully initialised SDRAM - we really don't care which) @@ -95,6 +124,7 @@ car_init_ret: #ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp #endif +#endif
/* Reserve space on stack for global data */ subl $GENERATED_GBL_DATA_SIZE, %esp @@ -109,6 +139,13 @@ car_init_ret: movl %esp, %edi rep stosb
+#ifdef CONFIG_HAVE_FSP + /* Store HOB list */ + movl %esp, %edx + addl $GD_HOB_LIST, %edx + movl %esi, (%edx) +#endif + /* Setup first parameter to setup_gdt, pointer to global_data */ movl %esp, %eax
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 48bbd1a..03d491a 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -47,6 +47,9 @@ struct arch_global_data { enum pei_boot_mode_t pei_boot_mode; const struct pch_gpio_map *gpio_map; /* board GPIO map */ struct memory_info meminfo; /* Memory information */ +#ifdef CONFIG_HAVE_FSP + void *hob_list; /* FSP HOB list */ +#endif };
#endif diff --git a/arch/x86/lib/asm-offsets.c b/arch/x86/lib/asm-offsets.c index 50a488f..70ccf1b 100644 --- a/arch/x86/lib/asm-offsets.c +++ b/arch/x86/lib/asm-offsets.c @@ -18,5 +18,8 @@ int main(void) { DEFINE(GD_BIST, offsetof(gd_t, arch.bist)); +#ifdef CONFIG_HAVE_FSP + DEFINE(GD_HOB_LIST, offsetof(gd_t, arch.hob_list)); +#endif return 0; }

Hi Bin,
On 4 December 2014 at 08:02, Bin Meng bmeng.cn@gmail.com wrote:
Per Intel FSP architecture specification, FSP provides 3 routines for bootloader to call. The first one is the TempRamInit (aka Cache-As-Ram initialization) and the second one is the FspInit which does the memory bring up (like MRC for other x86 targets) and chipset initialization. Those two routines have to be called before U-Boot jumping to board_init_f in start.S.
The FspInit() will return several memory blocks called Hand Off Blocks (HOBs) whose format is described in Platform Initialization (PI) specification (part of the UEFI specication) to the bootloader. Save this HOB address to the U-Boot global data for later use.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/cpu/start.S | 37 +++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/global_data.h | 3 +++ arch/x86/lib/asm-offsets.c | 3 +++ 3 files changed, 43 insertions(+)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index f9662fb..b4a69d2 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -75,6 +75,35 @@ early_board_init_ret: jmp car_init .globl car_init_ret car_init_ret: +#ifdef CONFIG_HAVE_FSP
Can we put this code into car_init?
/*
* The FSP TempRamInit initializes the ecx and edx registers to
* point to a temporary but writable memory range (Cache-As-RAM).
* ecx: the start of this temporary memory range,
* edx: the end of this range.
*/
/* stack grows down from top of CAR */
movl %edx, %esp
movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax
xorl %edx, %edx
xorl %ecx, %ecx
call FspInitWrapper
What does this return? Can you add a a comment?
+.global fsp_init_done +fsp_init_done:
/*
* We come here from FspInit with eax pointing to the HOB list.
* Save eax to esi temporarily.
*/
movl %eax, %esi
/*
* Re-initialize the ebp (BIST) to zero, as we already reach here
* which means we passed BIST testing before.
How do you know we already reached here?
*/
xorl %ebp, %ebp
+#else /* * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, * or fully initialised SDRAM - we really don't care which) @@ -95,6 +124,7 @@ car_init_ret: #ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp #endif +#endif
/* Reserve space on stack for global data */ subl $GENERATED_GBL_DATA_SIZE, %esp
@@ -109,6 +139,13 @@ car_init_ret: movl %esp, %edi rep stosb
+#ifdef CONFIG_HAVE_FSP
/* Store HOB list */
movl %esp, %edx
addl $GD_HOB_LIST, %edx
movl %esi, (%edx)
+#endif
/* Setup first parameter to setup_gdt, pointer to global_data */ movl %esp, %eax
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 48bbd1a..03d491a 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -47,6 +47,9 @@ struct arch_global_data { enum pei_boot_mode_t pei_boot_mode; const struct pch_gpio_map *gpio_map; /* board GPIO map */ struct memory_info meminfo; /* Memory information */ +#ifdef CONFIG_HAVE_FSP
void *hob_list; /* FSP HOB list */
+#endif };
#endif diff --git a/arch/x86/lib/asm-offsets.c b/arch/x86/lib/asm-offsets.c index 50a488f..70ccf1b 100644 --- a/arch/x86/lib/asm-offsets.c +++ b/arch/x86/lib/asm-offsets.c @@ -18,5 +18,8 @@ int main(void) { DEFINE(GD_BIST, offsetof(gd_t, arch.bist)); +#ifdef CONFIG_HAVE_FSP
DEFINE(GD_HOB_LIST, offsetof(gd_t, arch.hob_list));
+#endif return 0; } -- 1.8.2.1
Regards, Simon

Hi Simon,
On Fri, Dec 5, 2014 at 7:40 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 4 December 2014 at 08:02, Bin Meng bmeng.cn@gmail.com wrote:
Per Intel FSP architecture specification, FSP provides 3 routines for bootloader to call. The first one is the TempRamInit (aka Cache-As-Ram initialization) and the second one is the FspInit which does the memory bring up (like MRC for other x86 targets) and chipset initialization. Those two routines have to be called before U-Boot jumping to board_init_f in start.S.
The FspInit() will return several memory blocks called Hand Off Blocks (HOBs) whose format is described in Platform Initialization (PI) specification (part of the UEFI specication) to the bootloader. Save this HOB address to the U-Boot global data for later use.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/cpu/start.S | 37 +++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/global_data.h | 3 +++ arch/x86/lib/asm-offsets.c | 3 +++ 3 files changed, 43 insertions(+)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index f9662fb..b4a69d2 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -75,6 +75,35 @@ early_board_init_ret: jmp car_init .globl car_init_ret car_init_ret: +#ifdef CONFIG_HAVE_FSP
Can we put this code into car_init?
Yes, there codes can be put into car_init. I actually considered putting them to car_init before. In the FSP case, the car_init will not return to car_init_ret. Instead it will jump directly to reserving space on stack for global data. This may look weird why car_init does not return to car_init_ret. But it is not a big problem. I will move it to car_init in v2, and put a comment in start.S to explain.
/*
* The FSP TempRamInit initializes the ecx and edx registers to
* point to a temporary but writable memory range (Cache-As-RAM).
* ecx: the start of this temporary memory range,
* edx: the end of this range.
*/
/* stack grows down from top of CAR */
movl %edx, %esp
movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax
xorl %edx, %edx
xorl %ecx, %ecx
call FspInitWrapper
What does this return? Can you add a a comment?
Sure.
+.global fsp_init_done +fsp_init_done:
/*
* We come here from FspInit with eax pointing to the HOB list.
* Save eax to esi temporarily.
*/
movl %eax, %esi
/*
* Re-initialize the ebp (BIST) to zero, as we already reach here
* which means we passed BIST testing before.
How do you know we already reached here?
In the car_init, the BIST testing will be done before any call to FSP to enable the CAR. If that fails, it will never get here.
[snip]
Regards, Bin
participants (2)
-
Bin Meng
-
Simon Glass