Currently, the GDT is either located in FLASH or in the non-relocated
U-Boot image in RAM. Both of these locations are unsafe as those
locations can be erased during a U-Boot update. Move the GDT into the
highest available memory location and relocate U-Boot to just below it
---
 cpu/i386/start.S   |  110 +++++++++++++++++++++++++++++++++++++++++++++++++---
 cpu/i386/start16.S |   28 +++----------
 2 files changed, 111 insertions(+), 27 deletions(-)

diff --git a/cpu/i386/start.S b/cpu/i386/start.S
index e1d4492..8874470 100644
--- a/cpu/i386/start.S
+++ b/cpu/i386/start.S
@@ -49,13 +49,8 @@ _i386boot_start:
        movl    %eax, %cr0
        wbinvd
 
-       lidt    blank_idt_ptr
-
-       /* Tell 32-bit code it is being entered from  */
+       /* Tell 32-bit code it is being entered from an in-RAM copy */
        movw    $0x0000, %bx
-
-       /* Flush the prefetch queue */
-       jmp     _start
 _start:
        /* This is the 32-bit cold-reset entry point */
 
@@ -67,6 +62,9 @@ _start:
        movw    %ax,%es
        movw    %ax,%ss
 
+       /* Clear the interupt vectors */
+       lidt    blank_idt_ptr
+
        /*
         * Skip low-level board and memory initialization if not starting
         * from cold-reset. This allows us to do a fail safe boot-strap
@@ -102,6 +100,53 @@ mem_init_ret:
        jmp     get_mem_size
 get_mem_size_ret:
 
+       /*
+        * We are now in 'Flat Protected Mode' and we know how much memory
+        * the board has. The (temporary) Global Descriptor Table is not
+        * in a 'Safe' place (it is either in Flash which can be erased or
+        * reprogrammed or in a fail-safe boot-strap image which could be
+        * over-ridden).
+        *
+        * Move the final gdt to a safe place (top of RAM) and load it.
+        * This is not a trivial excercise - the lgdt instruction does not
+        * have a register operand (memory only) and we may well be
+        * running from Flash, so self modifying code will not work here.
+        * To overcome this, we copy a stub into upper memory along with
+        * the GDT.
+        */
+
+       /* Reduce upper memory limit by (Stub + GDT Pointer + GDT) */
+       subl    $(end_gdt_setup - start_gdt_setup), %eax
+
+       /* Copy the GDT and Stub */
+       movl    $start_gdt_setup, %esi
+       movl    %eax, %edi
+       movl    $(end_gdt_setup - start_gdt_setup), %ecx
+       shrl    $2, %ecx
+       cld
+       rep     movsl
+
+       /* write the lgdt 'parameter' */
+       subl    $(jmp_instr - start_gdt_setup - 4), %ebp
+       addl    %eax, %ebp
+       movl    $(gdt_ptr - start_gdt_setup), %ebx
+       addl    %eax, %ebx
+       movl    %ebx, (%ebp)
+
+       /* write the gdt address into the pointer */
+       movl    $(gdt_addr - start_gdt_setup), %ebp
+       addl    %eax, %ebp
+       movl    $(gdt - start_gdt_setup), %ebx
+       addl    %eax, %ebx
+       movl    %ebx, (%ebp)
+
+       /* Save the return address */
+       movl    $load_gdt_ret, %ebp
+
+       /* Load the new (safe) Global Descriptor Table */
+       jmp     *%eax
+
+load_gdt_ret:
        /* Check we have enough memory for stack */
        movl    $CONFIG_SYS_STACK_SIZE, %ecx
        cmpl    %ecx, %eax
@@ -172,3 +217,56 @@ stack_ok:
 die:   hlt
        jmp     die
        hlt
+
+blank_idt_ptr:
+       .word   0               /* limit */
+       .long   0               /* base */
+
+.align 4
+start_gdt_setup:
+       lgdt    gdt_ptr
+jmp_instr:
+       jmp     *%ebp
+
+.align 4
+gdt_ptr:
+       .word   0x30            /* limit (48 bytes = 6 GDT entries) */
+gdt_addr:
+       .long   gdt             /* base */
+
+       /* The GDT table ...
+        *
+        *       Selector       Type
+        *       0x00           NULL
+        *       0x08           Unused
+        *       0x10           32bit code
+        *       0x18           32bit data/stack
+        *       0x20           16bit code
+        *       0x28           16bit data/stack
+        */
+
+.align 4
+gdt:
+       .word   0, 0, 0, 0      /* NULL  */
+       .word   0, 0, 0, 0      /* unused */
+
+       .word   0xFFFF          /* 4Gb - (0x100000*0x1000 = 4Gb) */
+       .word   0               /* base address = 0 */
+       .word   0x9B00          /* code read/exec */
+       .word   0x00CF          /* granularity = 4096, 386 (+5th nibble of 
limit) */
+
+       .word   0xFFFF          /* 4Gb - (0x100000*0x1000 = 4Gb) */
+       .word   0x0             /* base address = 0 */
+       .word   0x9300          /* data read/write */
+       .word   0x00CF          /* granularity = 4096, 386 (+5th nibble of 
limit) */
+
+       .word   0xFFFF          /* 64kb */
+       .word   0               /* base address = 0 */
+       .word   0x9b00          /* data read/write */
+       .word   0x0010          /* granularity = 1  (+5th nibble of limit) */
+
+       .word   0xFFFF          /* 64kb */
+       .word   0               /* base address = 0 */
+       .word   0x9300          /* data read/write */
+       .word   0x0010          /* granularity = 1 (+5th nibble of limit) */
+end_gdt_setup:
diff --git a/cpu/i386/start16.S b/cpu/i386/start16.S
index 1caa686..3e8b2cc 100644
--- a/cpu/i386/start16.S
+++ b/cpu/i386/start16.S
@@ -44,11 +44,9 @@ board_init16_ret:
        movl    %eax, %cr0
        wbinvd
 
-       /* load the descriptor tables */
-o32 cs lidt    blank_idt_ptr
+       /* load the temporary Global Descriptor Table */
 o32 cs lgdt    gdt_ptr
 
-
        /* Now, we enter protected mode */
        movl    %cr0, %eax
        orl     $1,%eax
@@ -70,13 +68,13 @@ code32start:
        .long   _start          /* offset */
        .word   0x10            /* segment */
 
-.global blank_idt_ptr
-blank_idt_ptr:
-       .word   0               /* limit */
-       .long   0               /* base */
-
+/*
+ * The following Global Descriptor Table is just enough to get us into
+ * 'Flat Protected Mode' - It will be discarded as soon as the final
+ * GDT is setup in a safe location in RAM
+ */
 gdt_ptr:
-       .word   0x30            /* limit (48 bytes = 6 GDT entries) */
+       .word   0x20            /* limit (32 bytes = 4 GDT entries) */
        .long   BOOT_SEG + gdt  /* base */
 
        /* The GDT table ...
@@ -86,8 +84,6 @@ gdt_ptr:
         *       0x08           Unused
         *       0x10           32bit code
         *       0x18           32bit data/stack
-        *       0x20           16bit code
-        *       0x28           16bit data/stack
         */
 
 gdt:
@@ -103,13 +99,3 @@ gdt:
        .word   0x0             /* base address = 0 */
        .word   0x9300          /* data read/write */
        .word   0x00CF          /* granularity = 4096, 386 (+5th nibble of 
limit) */
-
-       .word   0xFFFF          /* 64kb */
-       .word   0               /* base address = 0 */
-       .word   0x9b00          /* data read/write */
-       .word   0x0010          /* granularity = 1  (+5th nibble of limit) */
-
-       .word   0xFFFF          /* 64kb */
-       .word   0               /* base address = 0 */
-       .word   0x9300          /* data read/write */
-       .word   0x0010          /* granularity = 1 (+5th nibble of limit) */
-- 
1.7.0.2.182.ge007

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to