]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Port Intel .asm to GAS S
authorgikidy <gikidy@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 20 Feb 2009 08:22:04 +0000 (08:22 +0000)
committergikidy <gikidy@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 20 Feb 2009 08:22:04 +0000 (08:22 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7557 6f19259b-4bc3-4df7-8a09-765794883524

DuetPkg/BootSector/efi32.S [new file with mode: 0644]
DuetPkg/BootSector/start.S
DuetPkg/BootSector/start32.S [new file with mode: 0644]

diff --git a/DuetPkg/BootSector/efi32.S b/DuetPkg/BootSector/efi32.S
new file mode 100644 (file)
index 0000000..421271c
--- /dev/null
@@ -0,0 +1,581 @@
+#------------------------------------------------------------------------------\r
+#*\r
+#*   Copyright 2006, Intel Corporation                                                         \r
+#*   All rights reserved. This program and the accompanying materials                          \r
+#*   are licensed and made available under the terms and conditions of the BSD License         \r
+#*   which accompanies this distribution.  The full text of the license may be found at        \r
+#*   http://opensource.org/licenses/bsd-license.php                                            \r
+#*                                                                                             \r
+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+#*   \r
+#*    efi32.asm\r
+#*  \r
+#*   Abstract:\r
+#*\r
+#------------------------------------------------------------------------------\r
+\r
+##############################################################################\r
+# Now in 32-bit protected mode.\r
+##############################################################################\r
+\r
+        .486: \r
+        #.MODEL flat\r
+        .stack: \r
+        .code: \r
+        .org 0x21000\r
+\r
+.equ                 DEFAULT_HANDLER_SIZE, INT1 - INT0\r
+\r
+.macro jmpCommonIdtEntry  \r
+    # jmp     commonIdtEntry - this must be hand coded to keep the assembler from\r
+    #                          using a 8 bit reletive jump when the entries are\r
+    #                          within 255 bytes of the common entry.  This must\r
+    #                          be done to maintain the consistency of the size\r
+    #                          of entry points...\r
+    .byte   0xe9                        # jmp 16 bit relative\r
+    .long      commonIdtEntry - . - 4  # A problem     \r
+.endm\r
+\r
+Start:  \r
+    movw    %ax, %ds\r
+    movw    %ax, %es\r
+    movw    %ax, %fs\r
+    movw    %ax, %gs\r
+    movw    %ax, %ss\r
+    movl    $0x001ffff0, %esp\r
+\r
+    call    ClearScreen\r
+\r
+    # Populate IDT with meaningful offsets for exception handlers...\r
+    sidt    Idtr            \r
+\r
+    movl    Halt, %eax\r
+    movl    %eax, %ebx                  # use bx to copy 15..0 to descriptors\r
+    shrl    $16, %eax                   # use ax to copy 31..16 to descriptors \r
+    movl    $0x78, %ecx                 # 78h IDT entries to initialize with unique entry points (exceptions)\r
+    movl    (Idtr + 2), %esi\r
+    movl    (%esi), %edi\r
+\r
+LOOP_1:                                             # loop through all IDT entries exception handlers and initialize to default handler\r
+    movw    %bx, (%edi)                         # write bits 15..0 of offset\r
+    movw    $0x20, 2(%edi)                      # SYS_CODE_SEL from GDT\r
+    movw    $(0x0e00 | 0x8000), 4(%edi)                # type = 386 interrupt gate, present\r
+    movw    %ax, 6(%edi)                        # write bits 31..16 of offset\r
+    addl    $8, %edi                            # move up to next descriptor\r
+    addw    DEFAULT_HANDLER_SIZE, %bx           # move to next entry point\r
+    loopl   LOOP_1                                 # loop back through again until all descriptors are initialized\r
+\r
+    ## at this point edi contains the offset of the descriptor for INT 20\r
+    ## and bx contains the low 16 bits of the offset of the default handler\r
+    ## so initialize all the rest of the descriptors with these two values...\r
+#    mov     ecx, 101                            ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)\r
+#@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler\r
+#    mov     word ptr [edi], bx                  ; write bits 15..0 of offset\r
+#    mov     word ptr [edi+2], 20h               ; SYS_CODE_SEL from GDT\r
+#    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present\r
+#    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset\r
+#    add     edi, 8                              ; move up to next descriptor\r
+#    loop    @b                                  ; loop back through again until all descriptors are initialized\r
+\r
+\r
+##  DUMP    location of IDT and several of the descriptors\r
+#    mov     ecx, 8\r
+#    mov     eax, [offset Idtr + 2]\r
+#    mov     eax, [eax]\r
+#    mov     edi, 0b8000h\r
+#    call    PrintDword\r
+#    mov     esi, eax\r
+#    mov     edi, 0b80a0h\r
+#    jmp     OuterLoop\r
+\r
+##    \r
+## just for fun, let's do a software interrupt to see if we correctly land in the exception handler...\r
+#    mov     eax, 011111111h\r
+#    mov     ebx, 022222222h\r
+#    mov     ecx, 033333333h\r
+#    mov     edx, 044444444h\r
+#    mov     ebp, 055555555h\r
+#    mov     esi, 066666666h\r
+#    mov     edi, 077777777h\r
+#    push    011111111h\r
+#    push    022222222h\r
+#    push    033333333h\r
+#    int     119\r
+\r
+\r
+    movl    $0x22000, %esi              # esi = 22000\r
+    movl    0x14(%esi), %eax            # eax = [22014]\r
+    addl    %eax, %esi                  # esi = 22000 + [22014] = Base of EFILDR.C\r
+    movl    0x3c(%esi), %ebp            # ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C\r
+    addl    %esi, %ebp\r
+    movl    0x34(%ebp), %edi            # edi = [[22000 + [22014] + 3c] + 30] = ImageBase\r
+    movl    0x28(%ebp), %eax            # eax = [[22000 + [22014] + 3c] + 24] = EntryPoint\r
+    addl    %edi, %eax                  # eax = ImageBase + EntryPoint\r
+    movl    %eax, EfiLdrOffset             # Modify far jump instruction for correct entry point\r
+\r
+    movw    6(%ebp), %bx                # bx = Number of sections\r
+    xorl    %eax, %eax\r
+    movw    0x14(%ebp), %ax             # ax = Optional Header Size\r
+    addl    %eax, %ebp\r
+    addl    $0x18, %ebp                 # ebp = Start of 1st Section\r
+\r
+SectionLoop: \r
+    pushl   %esi                        # Save Base of EFILDR.C\r
+    pushl   %edi                        # Save ImageBase\r
+    addl    0x14(%ebp), %esi            # esi = Base of EFILDR.C + PointerToRawData\r
+    addl    0x0c(%ebp), %edi            # edi = ImageBase + VirtualAddress\r
+    movl    0x10(%ebp), %ecx            # ecs = SizeOfRawData\r
+\r
+    cld\r
+    shrl    $2, %ecx\r
+    rep\r
+    movsl\r
+\r
+    popl    %edi                        # Restore ImageBase\r
+    popl    %esi                        # Restore Base of EFILDR.C\r
+\r
+    addw    $0x28, %bp                  # ebp = ebp + 028h = Pointer to next section record\r
+    decw    %bx\r
+    cmpw    $0, %bx\r
+    jne     SectionLoop\r
+\r
+    movzwl  Idtr, %eax                  # get size of IDT\r
+    incl    %eax\r
+    addl    Idtr + 2, %eax             # add to base of IDT to get location of memory map... \r
+    pushl   %eax                        # push memory map location on stack for call to EFILDR...\r
+\r
+    pushl   %eax                        # push return address (useless, just for stack balance)\r
+    .byte   0xb8\r
+EfiLdrOffset: \r
+    .long   0x00401000                  # Offset of EFILDR\r
+# mov eax, 401000h\r
+    pushl   %eax\r
+    ret\r
+\r
+#    db      "**** DEFAULT IDT ENTRY ***",0\r
+    .align 0x2\r
+Halt: \r
+INT0: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $0x0\r
+    jmpCommonIdtEntry \r
+#    db      0e9h                        ; jmp 16 bit reletive \r
+#    dd      commonIdtEntry - $ - 4      ;  offset to jump to\r
+\r
+INT1: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $0x1\r
+    jmpCommonIdtEntry \r
+\r
+INT2: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $0x2\r
+    jmpCommonIdtEntry \r
+\r
+INT3: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $0x3\r
+    jmpCommonIdtEntry \r
+\r
+INT4: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $0x4\r
+    jmpCommonIdtEntry \r
+\r
+INT5: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $0x5\r
+    jmpCommonIdtEntry \r
+\r
+INT6: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $0x6\r
+    jmpCommonIdtEntry \r
+\r
+INT7: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $0x7\r
+    jmpCommonIdtEntry \r
+\r
+INT8: \r
+#   Double fault causes an error code to be pushed so no phony push necessary\r
+    nop\r
+    nop\r
+    pushl   $0x8\r
+    jmpCommonIdtEntry \r
+\r
+INT9: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $0x9\r
+    jmpCommonIdtEntry \r
+\r
+INT10: \r
+#   Invalid TSS causes an error code to be pushed so no phony push necessary\r
+    nop\r
+    nop\r
+    pushl   $10\r
+    jmpCommonIdtEntry \r
+\r
+INT11: \r
+#   Segment Not Present causes an error code to be pushed so no phony push necessary\r
+    nop\r
+    nop\r
+    pushl   $11\r
+    jmpCommonIdtEntry \r
+\r
+INT12: \r
+#   Stack fault causes an error code to be pushed so no phony push necessary\r
+    nop\r
+    nop\r
+    pushl   $12\r
+    jmpCommonIdtEntry \r
+\r
+INT13: \r
+#   GP fault causes an error code to be pushed so no phony push necessary\r
+    nop\r
+    nop\r
+    pushl   $13\r
+    jmpCommonIdtEntry \r
+\r
+INT14: \r
+#   Page fault causes an error code to be pushed so no phony push necessary\r
+    nop\r
+    nop\r
+    pushl   $14\r
+    jmpCommonIdtEntry \r
+\r
+INT15: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $15\r
+    jmpCommonIdtEntry \r
+\r
+INT16: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $16\r
+    jmpCommonIdtEntry \r
+\r
+INT17: \r
+#   Alignment check causes an error code to be pushed so no phony push necessary\r
+    nop\r
+    nop\r
+    pushl   $17\r
+    jmpCommonIdtEntry \r
+\r
+INT18: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $18\r
+    jmpCommonIdtEntry \r
+\r
+INT19: \r
+    pushl   $0x0    # push error code place holder on the stack\r
+    pushl   $19\r
+    jmpCommonIdtEntry \r
+\r
+INTUnknown: \r
+.rept  (0x78 - 20)\r
+    pushl   $0x0    # push error code place holder on the stack\r
+#   push    $0xxx   # push vector number\r
+    .byte   0x6a\r
+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number\r
+    jmpCommonIdtEntry \r
+.endr\r
+\r
+commonIdtEntry: \r
+    pushal\r
+    movl    %esp, %ebp\r
+##\r
+##  At this point the stack looks like this:\r
+##\r
+##      eflags\r
+##      Calling CS\r
+##      Calling EIP\r
+##      Error code or 0\r
+##      Int num or 0ffh for unknown int num\r
+##      eax\r
+##      ecx\r
+##      edx\r
+##      ebx\r
+##      esp\r
+##      ebp\r
+##      esi\r
+##      edi <------- ESP, EBP\r
+##      \r
+\r
+    call    ClearScreen\r
+    movl    String1, %esi\r
+    call    PrintString\r
+    movl    32(%ebp), %eax      ## move Int number into EAX \r
+    cmpl    $19, %eax\r
+    ja      PrintDefaultString\r
+PrintExceptionString: \r
+    shll    $2, %eax            ## multiply by 4 to get offset from StringTable to actual string address\r
+    addl    StringTable, %eax\r
+    movl    (%eax), %esi\r
+    jmp     PrintTheString\r
+PrintDefaultString: \r
+    movl    IntUnknownString, %esi\r
+    # patch Int number\r
+    movl    %eax, %edx\r
+    call    A2C\r
+    movb    %al, 1(%esi)\r
+    movl    %edx, %eax\r
+    shrl    $4, %eax\r
+    call    A2C\r
+    movb    %al, (%esi)\r
+PrintTheString:        \r
+    call    PrintString\r
+    movl    String2, %esi\r
+    call    PrintString\r
+    movl    44(%ebp), %eax         # CS\r
+    call    PrintDword\r
+    movb    ':', %al\r
+    movb    %al, (%edi)\r
+    addl    $2, %edi\r
+    movl    40(%ebp), %eax         # EIP\r
+    call    PrintDword\r
+    movl    String3, %esi\r
+    call    PrintString\r
+\r
+    movl    $0xb8140, %edi\r
+\r
+    movl    StringEax, %esi           # eax\r
+    call    PrintString\r
+    movl    28(%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    StringEbx, %esi           # ebx\r
+    call    PrintString\r
+    movl    16(%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    StringEcx, %esi           # ecx\r
+    call    PrintString\r
+    movl    24(%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    StringEdx, %esi           # edx\r
+    call    PrintString\r
+    movl    20(%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    StringEcode, %esi         # error code\r
+    call    PrintString\r
+    movl    36(%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    $0xb81e0, %edi\r
+\r
+    movl    StringEsp, %esi           # esp\r
+    call    PrintString\r
+    movl    12(%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    StringEbp, %esi           # ebp\r
+    call    PrintString\r
+    movl    8(%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    StringEsi, %esi           # esi\r
+    call    PrintString\r
+    movl    4(%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    StringEdi, %esi          # edi\r
+    call    PrintString\r
+    movl    (%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    StringEflags, %esi       # eflags\r
+    call    PrintString\r
+    movl    48(%ebp), %eax\r
+    call    PrintDword\r
+\r
+    movl    $0xb8320, %edi\r
+\r
+    movl    %ebp, %esi\r
+    addl    $52, %esi\r
+    movl    $8, %ecx\r
+\r
+\r
+OuterLoop: \r
+    pushl   %ecx\r
+    movl    $8, %ecx\r
+    movl    %edi, %edx\r
+\r
+InnerLoop: \r
+    movl    (%esi), %eax\r
+    call    PrintDword\r
+    addl    $4, %esi\r
+    movb    ' ', %al \r
+    movb    %al, (%edi)\r
+    addl    $2, %edi\r
+    loop    InnerLoop\r
+\r
+    popl    %ecx\r
+    addl    $0xa0, %edx\r
+    movl    %edx, %edi\r
+    loop    OuterLoop\r
+\r
+\r
+    movl    $0xb8960, %edi\r
+\r
+    movl    40(%ebp), %eax # EIP\r
+    subl    $32*4, %eax\r
+    movl    %eax, %esi      # esi = eip - 32 DWORD linear (total 64 DWORD)\r
+\r
+    movl    $8, %ecx\r
+\r
+OuterLoop1: \r
+    pushl   %ecx\r
+    movl    $8, %ecx\r
+    movl    %edi, %edx\r
+\r
+InnerLoop1: \r
+    movl    (%esi), %eax\r
+    call    PrintDword\r
+    addl    $4, %esi\r
+    movb    ' ', %al \r
+    movb    %al, (%edi)\r
+    addl    $2, %edi\r
+    loop    InnerLoop1\r
+\r
+    popl    %ecx\r
+    addl    $0xa0, %edx\r
+    movl    %edx, %edi\r
+    loop    OuterLoop1\r
+\r
+\r
+\r
+#    wbinvd ; this intruction does not support in early than 486 arch\r
+LN_C1:    \r
+    jmp     LN_C1\r
+#\r
+# return\r
+#\r
+    movl    %ebp, %esp\r
+    popal\r
+    addl    $8, %esp # error code and INT number\r
+\r
+    iretl\r
+\r
+\r
+PrintString: \r
+    pushl   %eax\r
+LN_C2: \r
+    movb    (%esi), %al\r
+    cmpb    $0, %al\r
+    je      LN_C3\r
+    movb    %al, (%edi)\r
+    incl    %esi\r
+    addl    $2, %edi\r
+    jmp     LN_C2\r
+LN_C3: \r
+    popl    %eax\r
+    ret\r
+\r
+## EAX contains dword to print\r
+## EDI contains memory location (screen location) to print it to\r
+PrintDword: \r
+    pushl   %ecx\r
+    pushl   %ebx\r
+    pushl   %eax\r
+\r
+    movl    $8, %ecx\r
+looptop: \r
+    roll    $4, %eax\r
+    movb    %al, %bl\r
+    andb    $0xf, %bl\r
+    addb    '0', %bl\r
+    cmpb    '9', %bl\r
+    jle     LN_C4\r
+    addb    $7, %bl\r
+LN_C4: \r
+    movb    %bl, (%edi)\r
+    addl    $2, %edi\r
+    loop    looptop\r
+    #wbinvd\r
+\r
+    popl    %eax\r
+    popl    %ebx\r
+    popl    %ecx\r
+    ret\r
+\r
+ClearScreen: \r
+    pushl   %eax\r
+    pushl   %ecx\r
+\r
+    movb    ' ', %al\r
+    movb    $0xc, %ah\r
+    movl    $0xb8000, %edi\r
+    movl    $80*24, %ecx\r
+LN_C5: \r
+    movw    %ax, (%edi)\r
+    addl    $2, %edi\r
+    loop    LN_C5\r
+    movl    $0xb8000, %edi\r
+\r
+    popl    %ecx\r
+    popl    %eax\r
+\r
+    ret\r
+\r
+A2C: \r
+    andb    $0xf, %al\r
+    addb    '0', %al\r
+    cmpb    '9', %al\r
+    jle     LN_C6\r
+    addb    $7, %al\r
+LN_C6: \r
+    ret\r
+\r
+String1:            .asciz      "*** INT "\r
+\r
+Int0String:         .asciz      "00h Divide by 0 -"\r
+Int1String:         .asciz      "01h Debug exception -"\r
+Int2String:         .asciz      "02h NMI -"\r
+Int3String:         .asciz      "03h Breakpoint -"\r
+Int4String:         .asciz      "04h Overflow -"\r
+Int5String:         .asciz      "05h Bound -"\r
+Int6String:         .asciz      "06h Invalid opcode -"\r
+Int7String:         .asciz      "07h Device not available -"\r
+Int8String:         .asciz      "08h Double fault -"\r
+Int9String:         .asciz      "09h Coprocessor seg overrun (reserved) -"\r
+Int10String:        .asciz      "0Ah Invalid TSS -"\r
+Int11String:        .asciz      "0Bh Segment not present -"\r
+Int12String:        .asciz      "0Ch Stack fault -"\r
+Int13String:        .asciz      "0Dh General protection fault -"\r
+Int14String:        .asciz      "0Eh Page fault -"\r
+Int15String:        .asciz      "0Fh (Intel reserved) -"\r
+Int16String:        .asciz      "10h Floating point error -"\r
+Int17String:        .asciz      "11h Alignment check -"\r
+Int18String:        .asciz      "12h Machine check -"\r
+Int19String:        .asciz      "13h SIMD Floating-Point Exception -"\r
+IntUnknownString:   .asciz      "??h Unknown interrupt -"\r
+\r
+StringTable:   .long  Int0String, Int1String, Int2String, Int3String,    \\r
+                      Int4String, Int5String, Int6String, Int7String,    \\r
+                      Int8String, Int9String, Int10String, Int11String,  \\r
+                      Int12String, Int13String, Int14String, Int15String,\\r
+                      Int16String, Int17String, Int18String, Int19String\r
+\r
+String2:         .asciz  " HALT!! *** ("\r
+String3:         .asciz  ")"\r
+StringEax:       .asciz  "EAX="\r
+StringEbx:       .asciz  "EBX="\r
+StringEcx:       .asciz  "ECX="\r
+StringEdx:       .asciz  "EDX="\r
+StringEcode:     .asciz  "ECODE="\r
+StringEsp:       .asciz  "ESP="\r
+StringEbp:       .asciz  "EBP="\r
+StringEsi:       .asciz  "ESI="\r
+StringEdi:       .asciz  "EDI="\r
+StringEflags:    .asciz  "EFLAGS="\r
+\r
+Idtr:        .float  0\r
+\r
+    .org 0x21ffe\r
+BlockSignature: \r
+    .word   0xaa55\r
+\r
+\r
index 9d066541081fc15ce620acb4a7605f1ba1676645..d558652a9ad9d7ff0608525acc0e9d1fb7ec8279 100644 (file)
 #*\r
 #------------------------------------------------------------------------------\r
 \r
 #*\r
 #------------------------------------------------------------------------------\r
 \r
+\r
+\r
+\r
+\r
                \r
 .equ                        FAT_DIRECTORY_ENTRY_SIZE, 0x020\r
 .equ                        FAT_DIRECTORY_ENTRY_SHIFT, 5\r
                \r
 .equ                        FAT_DIRECTORY_ENTRY_SIZE, 0x020\r
 .equ                        FAT_DIRECTORY_ENTRY_SHIFT, 5\r
@@ -149,9 +153,9 @@ FatChainLoop:
         shrw    %ax                                 # FatOffset = ClusterNumber*3 / 2\r
         pushw   %si                                 # Save si\r
         movw    %ax, %si                            # si = FatOffset\r
         shrw    %ax                                 # FatOffset = ClusterNumber*3 / 2\r
         pushw   %si                                 # Save si\r
         movw    %ax, %si                            # si = FatOffset\r
-        shrw    %ax                                 # ax = FatOffset >> BLOCK_SHIFT\r
+        shrw    $BLOCK_SHIFT, %ax                   # ax = FatOffset >> BLOCK_SHIFT\r
         addw    ReservedSectors(%bp), %ax           # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)\r
         addw    ReservedSectors(%bp), %ax           # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)\r
-        andw    BLOCK_MASK,%si                      # si = FatOffset & BLOCK_MASK\r
+        andw    $BLOCK_MASK,%si                     # si = FatOffset & BLOCK_MASK\r
         cmpw    %dx, %ax                            # Compare FatSectorNumber to CachedFatSectorNumber\r
         je      SkipFatRead\r
         movw    $2, %bx\r
         cmpw    %dx, %ax                            # Compare FatSectorNumber to CachedFatSectorNumber\r
         je      SkipFatRead\r
         movw    $2, %bx\r
@@ -279,7 +283,7 @@ NotCrossing64KBoundry:
 DiskError: \r
         pushw %cs\r
         popw %ds\r
 DiskError: \r
         pushw %cs\r
         popw %ds\r
-        leaw %cs:ErrorString, %si\r
+        leaw ErrorString, %si\r
         movw $7, %cx\r
         jmp  PrintStringAndHalt\r
 \r
         movw $7, %cx\r
         jmp  PrintStringAndHalt\r
 \r
@@ -295,7 +299,7 @@ Halt:
 ErrorString: \r
         .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c\r
 \r
 ErrorString: \r
         .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c\r
 \r
-        #.org     0x0242 # For Code size overflow, Modified this just for pass build\r
+        .org     0x0241 # For Code size overflow, Modified this just for pass build\r
 LBAOffsetForBootSector: \r
         .long   0x0\r
 \r
 LBAOffsetForBootSector: \r
         .long   0x0\r
 \r
diff --git a/DuetPkg/BootSector/start32.S b/DuetPkg/BootSector/start32.S
new file mode 100644 (file)
index 0000000..3ddebfc
--- /dev/null
@@ -0,0 +1,928 @@
+#------------------------------------------------------------------------------\r
+#*\r
+#*   Copyright 2006 - 2007, Intel Corporation                                                         \r
+#*   All rights reserved. This program and the accompanying materials                          \r
+#*   are licensed and made available under the terms and conditions of the BSD License         \r
+#*   which accompanies this distribution.  The full text of the license may be found at        \r
+#*   http://opensource.org/licenses/bsd-license.php                                            \r
+#*                                                                                             \r
+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+#*   \r
+#*    start32.asm\r
+#*  \r
+#*   Abstract:\r
+#*\r
+#------------------------------------------------------------------------------\r
+\r
+        #.MODEL small\r
+        .stack: \r
+        .486p: \r
+        .code: \r
+\r
+.equ                        FAT_DIRECTORY_ENTRY_SIZE, 0x020\r
+.equ                        FAT_DIRECTORY_ENTRY_SHIFT, 5\r
+.equ                        BLOCK_SIZE, 0x0200\r
+.equ                        BLOCK_MASK, 0x01ff\r
+.equ                        BLOCK_SHIFT, 9\r
+\r
+        .org 0x0\r
+Ia32Jump: \r
+  jmp   BootSectorEntryPoint  # JMP inst    - 3 bytes\r
+  nop\r
+\r
+OemId:               .ascii  "INTEL   "    # OemId                           - 8 bytes\r
+SectorSize:          .word  0              # Sector Size                     - 2 bytes\r
+SectorsPerCluster:   .byte  0              # Sector Per Cluster              - 1 byte\r
+ReservedSectors:     .word  0              # Reserved Sectors                - 2 bytes\r
+NoFats:              .byte  0              # Number of FATs                  - 1 byte\r
+RootEntries:         .word  0              # Root Entries                    - 2 bytes\r
+Sectors:             .word  0              # Number of Sectors               - 2 bytes\r
+Media:               .byte  0              # Media                           - 1 byte\r
+SectorsPerFat16:     .word  0              # Sectors Per FAT for FAT12/FAT16 - 2 byte\r
+SectorsPerTrack:     .word  0              # Sectors Per Track               - 2 bytes\r
+Heads:               .word  0              # Heads                           - 2 bytes\r
+HiddenSectors:       .long  0              # Hidden Sectors                  - 4 bytes\r
+LargeSectors:        .long  0              # Large Sectors                   - 4 bytes\r
+\r
+#******************************************************************************\r
+#\r
+#The structure for FAT32 starting at offset 36 of the boot sector. (At this point, \r
+#the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)\r
+#\r
+#******************************************************************************\r
+\r
+SectorsPerFat32:     .long  0              # Sectors Per FAT for FAT32       - 4 bytes\r
+ExtFlags:            .word  0              # Mirror Flag                     - 2 bytes\r
+FSVersion:           .word  0              # File System Version             - 2 bytes\r
+RootCluster:         .long  0              # 1st Cluster Number of Root Dir  - 4 bytes\r
+FSInfo:              .word  0              # Sector Number of FSINFO         - 2 bytes\r
+BkBootSector:        .word  0              # Sector Number of Bk BootSector  - 2 bytes\r
+Reserved:            .fill 12,1,0          # Reserved Field                  - 12 bytes\r
+PhysicalDrive:       .byte  0              # Physical Drive Number           - 1 byte\r
+Reserved1:           .byte  0              # Reserved Field                  - 1 byte\r
+Signature:           .byte  0              # Extended Boot Signature         - 1 byte\r
+VolId:               .ascii  "    "        # Volume Serial Number            - 4 bytes\r
+FatLabel:            .ascii  "           " # Volume Label                    - 11 bytes\r
+FileSystemType:      .ascii  "FAT32   "    # File System Type                - 8 bytes\r
+\r
+BootSectorEntryPoint: \r
+        #ASSUME ds:@code\r
+        #ASSUME ss:@code\r
+      # ds = 1000, es = 2000 + x (size of first cluster >> 4)\r
+      # cx = Start Cluster of EfiLdr\r
+      # dx = Start Cluster of Efivar.bin\r
+\r
+# Re use the BPB data stored in Boot Sector\r
+        movw    $0x7c00, %bp\r
+\r
+\r
+        pushw   %cx\r
+# Read Efivar.bin\r
+#       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already\r
+        movw    $0x1900, %ax\r
+        movw    %ax, %es\r
+        testw   %dx, %dx\r
+        jnz     CheckVarStoreSize\r
+\r
+        movb    $1, %al\r
+NoVarStore: \r
+        pushw   %es\r
+# Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl\r
+        movb    %al, %es:($4)\r
+        jmp     SaveVolumeId\r
+\r
+CheckVarStoreSize: \r
+        movw    %dx, %di\r
+        cmpl    $0x4000, %ds:2(%di)\r
+        movb    $2, %al\r
+        jne     NoVarStore\r
+\r
+LoadVarStore: \r
+        movb    $0, %al\r
+        movb    %al, %es:($4)\r
+        movw    (%di), %cx\r
+#       ES:DI = 1500:0\r
+        xorw    %di, %di\r
+        pushw   %es\r
+        movw    $0x1500, %ax\r
+        movw    %ax, %es\r
+        call    ReadFile\r
+SaveVolumeId: \r
+        popw    %es\r
+        movw    VolId(%bp), %ax\r
+        movw    %ax, %es:($0)                       # Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId\r
+        movw    VolId+2(%bp), %ax\r
+        movw    %ax, %es:($2)\r
+\r
+# Read Efildr\r
+        popw    %cx\r
+#       cx    = Start Cluster of Efildr -> BS.com has filled already\r
+#       ES:DI = 2000:0, first cluster will be read again\r
+        xorw    %di, %di                            # di = 0\r
+        movw    $0x2000, %ax\r
+        movw    %ax, %es\r
+        call    ReadFile\r
+        movw    %cs, %ax\r
+        movw    %ax, %cs:JumpSegment\r
+JumpFarInstruction: \r
+        .byte   0xea\r
+JumpOffset: \r
+        .word   0x200\r
+JumpSegment: \r
+        .word   0x2000\r
+\r
+\r
+\r
+\r
+# ****************************************************************************\r
+# ReadFile\r
+#\r
+# Arguments:\r
+#   CX    = Start Cluster of File\r
+#   ES:DI = Buffer to store file content read from disk\r
+#\r
+# Return:\r
+#   (ES << 4 + DI) = end of file content Buffer\r
+#\r
+# ****************************************************************************\r
+ReadFile: \r
+# si      = NumberOfClusters\r
+# cx      = ClusterNumber\r
+# dx      = CachedFatSectorNumber\r
+# ds:0000 = CacheFatSectorBuffer\r
+# es:di   = Buffer to load file\r
+# bx      = NextClusterNumber\r
+        pusha\r
+        movw    $1, %si                             # NumberOfClusters = 1\r
+        pushw   %cx                                 # Push Start Cluster onto stack\r
+        movw    $0xfff, %dx                         # CachedFatSectorNumber = 0xfff\r
+FatChainLoop: \r
+        movw    %cx, %ax                            # ax = ClusterNumber    \r
+        andw    $0xfff8, %ax                        # ax = ax & 0xfff8\r
+        cmpw    $0xfff8, %ax                        # See if this is the last cluster\r
+        je      FoundLastCluster                    # Jump if last cluster found\r
+        movw    %cx, %ax                            # ax = ClusterNumber\r
+        shlw    $2, %ax                             # FatOffset = ClusterNumber * 4\r
+        pushw   %si                                 # Save si\r
+        movw    %ax, %si                            # si = FatOffset\r
+        shrw    $BLOCK_SHIFT, %ax                   # ax = FatOffset >> BLOCK_SHIFT\r
+        addw    ReservedSectors(%bp), %ax           # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)\r
+        andw    $BLOCK_MASK, %si                    # si = FatOffset & BLOCK_MASK\r
+        cmpw    %dx, %ax                            # Compare FatSectorNumber to CachedFatSectorNumber\r
+        je      SkipFatRead\r
+        movw    $2, %bx\r
+        pushw   %es\r
+        pushw   %ds\r
+        popw    %es\r
+        call    ReadBlocks                          # Read 2 blocks starting at AX storing at ES:DI\r
+        popw    %es\r
+        movw    %ax, %dx                            # CachedFatSectorNumber = FatSectorNumber\r
+SkipFatRead: \r
+        movw    (%si), %bx                          # bx = NextClusterNumber\r
+        movw    %cx, %ax                            # ax = ClusterNumber\r
+        popw    %si                                 # Restore si\r
+        decw    %bx                                 # bx = NextClusterNumber - 1\r
+        cmpw    %cx, %bx                            # See if (NextClusterNumber-1)==ClusterNumber\r
+        jne     ReadClusters\r
+        incw    %bx                                 # bx = NextClusterNumber\r
+        incw    %si                                 # NumberOfClusters++\r
+        movw    %bx, %cx                            # ClusterNumber = NextClusterNumber\r
+        jmp     FatChainLoop\r
+ReadClusters: \r
+        incw    %bx\r
+        popw    %ax                                 # ax = StartCluster\r
+        pushw   %bx                                 # StartCluster = NextClusterNumber\r
+        movw    %bx, %cx                            # ClusterNumber = NextClusterNumber\r
+        subw    $2, %ax                             # ax = StartCluster - 2\r
+        xorb    %bh, %bh\r
+        movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster\r
+        mulw    %bx                                 # ax = (StartCluster - 2) * SectorsPerCluster\r
+        addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster\r
+        pushw   %ax                                 # save start sector\r
+        movw    %si, %ax                            # ax = NumberOfClusters\r
+        mulw    %bx                                 # ax = NumberOfClusters * SectorsPerCluster\r
+        movw    %ax, %bx                            # bx = Number of Sectors\r
+        popw    %ax                                 # ax = Start Sector\r
+        call    ReadBlocks\r
+        movw    $1, %si                             # NumberOfClusters = 1\r
+        jmp     FatChainLoop\r
+FoundLastCluster: \r
+        popw    %cx\r
+        popa\r
+        ret\r
+\r
+\r
+# ****************************************************************************\r
+# ReadBlocks - Reads a set of blocks from a block device\r
+#\r
+# AX    = Start LBA\r
+# BX    = Number of Blocks to Read\r
+# ES:DI = Buffer to store sectors read from disk\r
+# ****************************************************************************\r
+\r
+# cx = Blocks\r
+# bx = NumberOfBlocks\r
+# si = StartLBA\r
+\r
+ReadBlocks: \r
+        pusha\r
+        addl    LBAOffsetForBootSector(%bp), %eax            # Add LBAOffsetForBootSector to Start LBA\r
+        addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA\r
+        movl    %eax, %esi                          # esi = Start LBA\r
+        movw    %bx, %cx                            # cx = Number of blocks to read\r
+ReadCylinderLoop: \r
+        movw    $0x7bfc, %bp                        # bp = 0x7bfc\r
+        movl    %esi, %eax                          # eax = Start LBA\r
+        xorl    %edx, %edx                          # edx = 0\r
+        movzwl  (%bp), %ebx                         # bx = MaxSector\r
+        divl    %ebx                                # ax = StartLBA / MaxSector\r
+        incw    %dx                                 # dx = (StartLBA % MaxSector) + 1\r
+\r
+        movw    (%bp), %bx                          # bx = MaxSector\r
+        subw    %dx, %bx                            # bx = MaxSector - Sector\r
+        incw    %bx                                 # bx = MaxSector - Sector + 1\r
+        cmpw    %bx, %cx                            # Compare (Blocks) to (MaxSector - Sector + 1)\r
+        jg      LimitTransfer\r
+        movw    %cx, %bx                            # bx = Blocks\r
+LimitTransfer: \r
+        pushw   %ax                                 # save ax\r
+        movw    %es, %ax                            # ax = es\r
+        shrw    $(BLOCK_SHIFT-4), %ax                # ax = Number of blocks into mem system\r
+        andw    $0x7f, %ax                          # ax = Number of blocks into current seg\r
+        addw    %bx, %ax                            # ax = End Block number of transfer\r
+        cmpw    $0x80, %ax                          # See if it crosses a 64K boundry\r
+        jle     NotCrossing64KBoundry               # Branch if not crossing 64K boundry\r
+        subw    $0x80, %ax                          # ax = Number of blocks past 64K boundry\r
+        subw    %ax, %bx                            # Decrease transfer size by block overage\r
+NotCrossing64KBoundry: \r
+        popw    %ax                                 # restore ax\r
+\r
+        pushw   %cx\r
+        movb    %dl, %cl                            # cl = (StartLBA % MaxSector) + 1 = Sector\r
+        xorw    %dx, %dx                            # dx = 0\r
+        divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  \r
+                                                    # dx = ax % (MaxHead + 1) = Head\r
+\r
+        pushw   %bx                                 # Save number of blocks to transfer\r
+        movb    %dl, %dh                            # dh = Head\r
+        movw    $0x7c00, %bp                        # bp = 0x7c00\r
+        movb    PhysicalDrive(%bp), %dl             # dl = Drive Number\r
+        movb    %al, %ch                            # ch = Cylinder\r
+        movb    %bl, %al                            # al = Blocks\r
+        movb    $2, %ah                             # ah = Function 2\r
+        movw    %di, %bx                            # es:bx = Buffer address\r
+        int     $0x13\r
+        jc      DiskError\r
+        popw    %bx\r
+        popw    %cx\r
+        movzwl  %bx, %ebx\r
+        addl    %ebx, %esi                          # StartLBA = StartLBA + NumberOfBlocks\r
+        subw    %bx, %cx                            # Blocks = Blocks - NumberOfBlocks\r
+        movw    %es, %ax\r
+        shlw    $(BLOCK_SHIFT-4), %bx\r
+        addw    %bx, %ax\r
+        movw    %ax, %es                            # es:di = es:di + NumberOfBlocks*BLOCK_SIZE\r
+        cmpw    $0, %cx\r
+        jne     ReadCylinderLoop\r
+        popa\r
+        ret\r
+\r
+DiskError: \r
+        pushw %cs\r
+        popw %ds\r
+        leaw ErrorString, %si\r
+        movw $7, %cx\r
+        jmp  PrintStringAndHalt\r
+\r
+PrintStringAndHalt: \r
+        movw $0xb800, %ax\r
+        movw %ax, %es\r
+        movw $160, %di\r
+        rep\r
+        movsw\r
+Halt: \r
+        jmp   Halt\r
+\r
+ErrorString: \r
+        .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c\r
+\r
+        .org     0x01fa  # Will cause build break\r
+LBAOffsetForBootSector: \r
+        .long   0x0\r
+\r
+        .org    0x01fe   # Will cause build break\r
+        .word   0xaa55\r
+\r
+#******************************************************************************\r
+#******************************************************************************\r
+#******************************************************************************\r
+\r
+.equ                 DELAY_PORT, 0x0ed           # Port to use for 1uS delay\r
+.equ                 KBD_CONTROL_PORT, 0x060     # 8042 control port     \r
+.equ                 KBD_STATUS_PORT, 0x064      # 8042 status port      \r
+.equ                 WRITE_DATA_PORT_CMD, 0x0d1  # 8042 command to write the data port\r
+.equ                 ENABLE_A20_CMD, 0x0df       # 8042 command to enable A20\r
+\r
+.org     0x200  # Will cause build break\r
+        jmp start\r
+Em64String: \r
+        .byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c\r
+\r
+start:  \r
+        movw %cs, %ax\r
+        movw %ax, %ds\r
+        movw %ax, %es\r
+        movw %ax, %ss\r
+        movw $MyStack, %sp\r
+\r
+#        mov ax,0b800h\r
+#        mov es,ax\r
+#        mov byte ptr es:[160],'a'\r
+#        mov ax,cs\r
+#        mov es,ax\r
+\r
+        movl $0, %ebx\r
+        leal MemoryMap, %edi\r
+MemMapLoop: \r
+        movl $0xe820, %eax\r
+        movl $20, %ecx\r
+        movl $0x534d4150, %edx  # 0x534d4150 = 'SMAP' \r
+        int  $0x15\r
+        jc  MemMapDone\r
+        addl $20, %edi\r
+        cmpl $0, %ebx\r
+        je  MemMapDone\r
+        jmp MemMapLoop\r
+MemMapDone: \r
+        leal MemoryMap, %eax\r
+        subl %eax, %edi                     # Get the address of the memory map\r
+        movl %edi, MemoryMapSize            # Save the size of the memory map\r
+\r
+        xorl    %ebx, %ebx\r
+        movw    %cs, %bx                    # BX=segment\r
+        shll    $4, %ebx                    # BX="linear" address of segment base\r
+        leal    GDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of gdt\r
+        movl    %eax, gdtr + 2            # Put address of gdt into the gdtr\r
+        leal    IDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of idt\r
+        movl    %eax, idtr + 2            # Put address of idt into the idtr\r
+        leal    MemoryMapSize(%ebx), %edx   # Physical base address of the memory map\r
+\r
+        addl $0x1000, %ebx                  # Source of EFI32\r
+        movl %ebx, JUMP+2\r
+        addl $0x1000, %ebx\r
+        movl %ebx, %esi                     # Source of EFILDR32\r
+\r
+#        mov ax,0b800h\r
+#        mov es,ax\r
+#        mov byte ptr es:[162],'b'\r
+#        mov ax,cs\r
+#        mov es,ax\r
+\r
+#\r
+# Enable A20 Gate \r
+#\r
+\r
+        movw $0x2401, %ax                   # Enable A20 Gate\r
+        int $0x15\r
+        jnc A20GateEnabled                  # Jump if it suceeded\r
+\r
+#\r
+# If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.\r
+#\r
+\r
+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller\r
+        jnz     Timeout8042                 # Jump if the 8042 timed out\r
+        outw    %ax, $DELAY_PORT            # Delay 1 uS\r
+        movb    $WRITE_DATA_PORT_CMD, %al   # 8042 cmd to write output port\r
+        outb    %al, $KBD_STATUS_PORT       # Send command to the 8042\r
+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller\r
+        jnz     Timeout8042                 # Jump if the 8042 timed out\r
+        movb    $ENABLE_A20_CMD, %al        # gate address bit 20 on\r
+        outb    %al, $KBD_CONTROL_PORT      # Send command to thre 8042\r
+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller\r
+        movw    $25, %cx                    # Delay 25 uS for the command to complete on the 8042\r
+Delay25uS: \r
+        outw    %ax, $DELAY_PORT            # Delay 1 uS\r
+        loopl   Delay25uS\r
+Timeout8042: \r
+\r
+\r
+A20GateEnabled: \r
+\r
+#\r
+# DISABLE INTERRUPTS - Entering Protected Mode\r
+#\r
+\r
+        cli\r
+\r
+#        mov ax,0b800h\r
+#        mov es,ax\r
+#        mov byte ptr es:[164],'c'\r
+#        mov ax,cs\r
+#        mov es,ax\r
+\r
+        .byte   0x66\r
+        lgdt    gdtr\r
+        .byte   0x66\r
+        lidt    idtr\r
+\r
+        movl    %cr0, %eax\r
+        orb     $1, %al\r
+        movl    %eax, %cr0\r
+\r
+        movl $0x008, %eax                   # Flat data descriptor\r
+        movl $0x00400000, %ebp              # Destination of EFILDR32\r
+        movl $0x00070000, %ebx              # Length of copy\r
+\r
+JUMP: \r
+# jmp far 0010:00020000\r
+        .byte 0x66\r
+        .byte 0xea\r
+        .long 0x00020000\r
+        .word 0x0010\r
+\r
+Empty8042InputBuffer: \r
+        movw $0, %cx\r
+Empty8042Loop: \r
+        outw    %ax, $DELAY_PORT            # Delay 1us\r
+        inb     $KBD_STATUS_PORT, %al       # Read the 8042 Status Port\r
+        andb    $0x2, %al                   # Check the Input Buffer Full Flag\r
+        loopnz  Empty8042Loop               # Loop until the input buffer is empty or a timout of 65536 uS\r
+        ret\r
+\r
+##############################################################################\r
+# data\r
+##############################################################################\r
+\r
+        .align 0x2\r
+\r
+gdtr:    .word GDT_END - GDT_BASE - 1   \r
+        .long 0                     # (GDT base gets set above)\r
+##############################################################################\r
+#   global descriptor table (GDT)\r
+##############################################################################\r
+\r
+        .align 0x2\r
+\r
+GDT_BASE: \r
+# null descriptor\r
+.equ                NULL_SEL, .-GDT_BASE\r
+        .word 0         # limit 15:0\r
+        .word 0         # base 15:0\r
+        .byte 0         # base 23:16\r
+        .byte 0         # type\r
+        .byte 0         # limit 19:16, flags\r
+        .byte 0         # base 31:24\r
+\r
+# linear data segment descriptor\r
+.equ            LINEAR_SEL, .-GDT_BASE\r
+        .word 0xFFFF    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0x92      # present, ring 0, data, expand-up, writable\r
+        .byte 0xCF      # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# linear code segment descriptor\r
+.equ            LINEAR_CODE_SEL, .-GDT_BASE\r
+        .word 0xFFFF    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0x9A      # present, ring 0, data, expand-up, writable\r
+        .byte 0xCF      # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# system data segment descriptor\r
+.equ            SYS_DATA_SEL, .-GDT_BASE\r
+        .word 0xFFFF    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0x92      # present, ring 0, data, expand-up, writable\r
+        .byte 0xCF      # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# system code segment descriptor\r
+.equ            SYS_CODE_SEL, .-GDT_BASE\r
+        .word 0xFFFF    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0x9A      # present, ring 0, data, expand-up, writable\r
+        .byte 0xCF      # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# spare segment descriptor\r
+.equ        SPARE3_SEL, .-GDT_BASE\r
+        .word 0         # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0         # present, ring 0, data, expand-up, writable\r
+        .byte 0         # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# spare segment descriptor\r
+.equ        SPARE4_SEL, .-GDT_BASE\r
+        .word 0         # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0         # present, ring 0, data, expand-up, writable\r
+        .byte 0         # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# spare segment descriptor\r
+.equ        SPARE5_SEL, .-GDT_BASE\r
+        .word 0         # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0         # present, ring 0, data, expand-up, writable\r
+        .byte 0         # page-granular, 32-bit\r
+        .byte 0\r
+\r
+GDT_END: \r
+\r
+        .align 0x2\r
+\r
+\r
+\r
+idtr:            .word IDT_END - IDT_BASE - 1  \r
+        .long 0                     # (IDT base gets set above)\r
+##############################################################################\r
+#   interrupt descriptor table (IDT)\r
+#\r
+#   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ\r
+#       mappings.  This implementation only uses the system timer and all other\r
+#       IRQs will remain masked.  The descriptors for vectors 33+ are provided\r
+#       for convenience.\r
+##############################################################################\r
+\r
+#idt_tag db "IDT",0     \r
+        .align 0x2\r
+\r
+IDT_BASE: \r
+# divide by zero (INT 0)\r
+.equ                DIV_ZERO_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# debug exception (INT 1)\r
+.equ                DEBUG_EXCEPT_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# NMI (INT 2)\r
+.equ                NMI_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# soft breakpoint (INT 3)\r
+.equ                BREAKPOINT_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# overflow (INT 4)\r
+.equ                OVERFLOW_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# bounds check (INT 5)\r
+.equ                BOUNDS_CHECK_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# invalid opcode (INT 6)\r
+.equ                INVALID_OPCODE_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# device not available (INT 7)\r
+.equ                DEV_NOT_AVAIL_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# double fault (INT 8)\r
+.equ                DOUBLE_FAULT_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# Coprocessor segment overrun - reserved (INT 9)\r
+.equ                RSVD_INTR_SEL1, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# invalid TSS (INT 0ah)\r
+.equ                INVALID_TSS_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# segment not present (INT 0bh)\r
+.equ                SEG_NOT_PRESENT_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# stack fault (INT 0ch)\r
+.equ                STACK_FAULT_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# general protection (INT 0dh)\r
+.equ                GP_FAULT_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# page fault (INT 0eh)\r
+.equ                PAGE_FAULT_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# Intel reserved - do not use (INT 0fh)\r
+.equ                RSVD_INTR_SEL2, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# floating point error (INT 10h)\r
+.equ                FLT_POINT_ERR_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# alignment check (INT 11h)\r
+.equ                ALIGNMENT_CHECK_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# machine check (INT 12h)\r
+.equ                MACHINE_CHECK_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# SIMD floating-point exception (INT 13h)\r
+.equ                SIMD_EXCEPTION_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# 85 unspecified descriptors, First 12 of them are reserved, the rest are avail\r
+        .fill 85 * 8, 1, 0\r
+\r
+# IRQ 0 (System timer) - (INT 68h)\r
+.equ                IRQ0_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 1 (8042 Keyboard controller) - (INT 69h)\r
+.equ                IRQ1_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)\r
+.equ                IRQ2_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 3 (COM 2) - (INT 6bh)\r
+.equ                IRQ3_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 4 (COM 1) - (INT 6ch)\r
+.equ                IRQ4_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 5 (LPT 2) - (INT 6dh)\r
+.equ                IRQ5_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 6 (Floppy controller) - (INT 6eh)\r
+.equ                IRQ6_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 7 (LPT 1) - (INT 6fh)\r
+.equ                IRQ7_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 8 (RTC Alarm) - (INT 70h)\r
+.equ                IRQ8_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 9 - (INT 71h)\r
+.equ                IRQ9_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 10 - (INT 72h)\r
+.equ                 IRQ10_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 11 - (INT 73h)\r
+.equ                 IRQ11_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 12 (PS/2 mouse) - (INT 74h)\r
+.equ                 IRQ12_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 13 (Floating point error) - (INT 75h)\r
+.equ                 IRQ13_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 14 (Secondary IDE) - (INT 76h)\r
+.equ                 IRQ14_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+# IRQ 15 (Primary IDE) - (INT 77h)\r
+.equ                 IRQ15_SEL, .-IDT_BASE\r
+        .word 0            # offset 15:0\r
+        .word SYS_CODE_SEL # selector 15:0\r
+        .byte 0            # 0 for interrupt gate\r
+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present\r
+        .word 0            # offset 31:16\r
+\r
+IDT_END: \r
+\r
+        .align 0x2\r
+\r
+MemoryMapSize:  .long 0\r
+MemoryMap:  .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0\r
+\r
+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r
+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r
+\r
+        .org 0x0fe0\r
+MyStack:    \r
+        # below is the pieces of the IVT that is used to redirect INT 68h - 6fh\r
+        #    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a\r
+        #    known low address (20f00) so it can be set up by PlMapIrqToVect in\r
+        #    8259.c\r
+\r
+        int $8\r
+        iret\r
+\r
+        int $9\r
+        iret\r
+\r
+        int $10\r
+        iret\r
+\r
+        int $11\r
+        iret\r
+\r
+        int $12\r
+        iret\r
+\r
+        int $13\r
+        iret\r
+\r
+        int $14\r
+        iret\r
+\r
+        int $15\r
+        iret\r
+\r
+\r
+        .org 0x0ffe\r
+BlockSignature: \r
+        .word 0xaa55\r
+\r
+\r