Commit e5aa8a9b1593f524af07318d4e84352b06a53402

Authored by Simon Glass
Committed by Bin Meng
1 parent 69ca6fd850

x86: Support a chained-boot development flow

Sometimes it is useful to jump into U-Boot directly from coreboot or UEFI
without any 16-bit init. This can help during development by allowing U-Boot
to avoid doing all the init required by the platform.

U-Boot expects its GDT to be set up correctly by its 16-bit code. If
coreboot doesn't do this (because it hasn't run the payload setup code yet)
then this won't happen.

In this case we cannot rely on the GDT settings. U-Boot will hang or crash
if these are wrong. Provide a development-only option to set up the GDT
correctly. This is just a hack so you can jump to U-Boot from any stage of
coreboot, not just at the end.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Showing 1 changed file with 80 additions and 0 deletions Side-by-side Diff

arch/x86/cpu/start.S
... ... @@ -18,6 +18,14 @@
18 18 #include <generated/generic-asm-offsets.h>
19 19 #include <generated/asm-offsets.h>
20 20  
  21 +/*
  22 + * Define this to boot U-Boot from a 32-bit program which sets the GDT
  23 + * differently. This can be used to boot directly from any stage of coreboot,
  24 + * for example, bypassing the normal payload-loading feature.
  25 + * This is only useful for development.
  26 + */
  27 +#undef LOAD_FROM_32_BIT
  28 +
21 29 .section .text
22 30 .code32
23 31 .globl _start
... ... @@ -68,6 +76,10 @@
68 76 /* Save table pointer */
69 77 movl %ecx, %esi
70 78  
  79 +#ifdef LOAD_FROM_32_BIT
  80 + lgdt gdt_ptr2
  81 +#endif
  82 +
71 83 /* Load the segement registers to match the GDT loaded in start16.S */
72 84 movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax
73 85 movw %ax, %fs
... ... @@ -220,4 +232,72 @@
220 232 .long 0
221 233 /* entry addr */
222 234 .long CONFIG_SYS_TEXT_BASE
  235 +
  236 +#ifdef LOAD_FROM_32_BIT
  237 + /*
  238 + * The following Global Descriptor Table is just enough to get us into
  239 + * 'Flat Protected Mode' - It will be discarded as soon as the final
  240 + * GDT is setup in a safe location in RAM
  241 + */
  242 +gdt_ptr2:
  243 + .word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */
  244 + .long gdt_rom2 /* base */
  245 +
  246 + /* Some CPUs are picky about GDT alignment... */
  247 + .align 16
  248 +.globl gdt_rom2
  249 +gdt_rom2:
  250 + /*
  251 + * The GDT table ...
  252 + *
  253 + * Selector Type
  254 + * 0x00 NULL
  255 + * 0x08 Unused
  256 + * 0x10 32bit code
  257 + * 0x18 32bit data/stack
  258 + */
  259 + /* The NULL Desciptor - Mandatory */
  260 + .word 0x0000 /* limit_low */
  261 + .word 0x0000 /* base_low */
  262 + .byte 0x00 /* base_middle */
  263 + .byte 0x00 /* access */
  264 + .byte 0x00 /* flags + limit_high */
  265 + .byte 0x00 /* base_high */
  266 +
  267 + /* Unused Desciptor - (matches Linux) */
  268 + .word 0x0000 /* limit_low */
  269 + .word 0x0000 /* base_low */
  270 + .byte 0x00 /* base_middle */
  271 + .byte 0x00 /* access */
  272 + .byte 0x00 /* flags + limit_high */
  273 + .byte 0x00 /* base_high */
  274 +
  275 + /*
  276 + * The Code Segment Descriptor:
  277 + * - Base = 0x00000000
  278 + * - Size = 4GB
  279 + * - Access = Present, Ring 0, Exec (Code), Readable
  280 + * - Flags = 4kB Granularity, 32-bit
  281 + */
  282 + .word 0xffff /* limit_low */
  283 + .word 0x0000 /* base_low */
  284 + .byte 0x00 /* base_middle */
  285 + .byte 0x9b /* access */
  286 + .byte 0xcf /* flags + limit_high */
  287 + .byte 0x00 /* base_high */
  288 +
  289 + /*
  290 + * The Data Segment Descriptor:
  291 + * - Base = 0x00000000
  292 + * - Size = 4GB
  293 + * - Access = Present, Ring 0, Non-Exec (Data), Writable
  294 + * - Flags = 4kB Granularity, 32-bit
  295 + */
  296 + .word 0xffff /* limit_low */
  297 + .word 0x0000 /* base_low */
  298 + .byte 0x00 /* base_middle */
  299 + .byte 0x93 /* access */
  300 + .byte 0xcf /* flags + limit_high */
  301 + .byte 0x00 /* base_high */
  302 +#endif