#------------------------------------------------------------------------------ #* #* Copyright 2006, Intel Corporation #* All rights reserved. This program and the accompanying materials #* are licensed and made available under the terms and conditions of the BSD License #* which accompanies this distribution. The full text of the license may be found at #* http://opensource.org/licenses/bsd-license.php #* #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #* #* efi32.asm #* #* Abstract: #* #------------------------------------------------------------------------------ ############################################################################## # Now in 32-bit protected mode. ############################################################################## .org 0x21000 .global _start _start: .equ DEFAULT_HANDLER_SIZE, INT1 - INT0 .macro jmpCommonIdtEntry # jmp commonIdtEntry - this must be hand coded to keep the assembler from # using a 8 bit reletive jump when the entries are # within 255 bytes of the common entry. This must # be done to maintain the consistency of the size # of entry points... .byte 0xe9 # jmp 16 bit relative .long commonIdtEntry - . - 4 # offset to jump to .endm Start: movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss movl $0x001ffff0, %esp call ClearScreen # Populate IDT with meaningful offsets for exception handlers... sidt Idtr movl Halt, %eax movl %eax, %ebx # use bx to copy 15..0 to descriptors shrl $16, %eax # use ax to copy 31..16 to descriptors movl $0x78, %ecx # 78h IDT entries to initialize with unique entry points (exceptions) movl (Idtr + 2), %esi movl (%esi), %edi LOOP_1: # loop through all IDT entries exception handlers and initialize to default handler movw %bx, (%edi) # write bits 15..0 of offset movw $0x20, 2(%edi) # SYS_CODE_SEL from GDT movw $(0x0e00 | 0x8000), 4(%edi) # type = 386 interrupt gate, present movw %ax, 6(%edi) # write bits 31..16 of offset addl $8, %edi # move up to next descriptor addw DEFAULT_HANDLER_SIZE, %bx # move to next entry point loopl LOOP_1 # loop back through again until all descriptors are initialized ## at this point edi contains the offset of the descriptor for INT 20 ## and bx contains the low 16 bits of the offset of the default handler ## so initialize all the rest of the descriptors with these two values... # mov ecx, 101 ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h) #@@: ; loop through all IDT entries exception handlers and initialize to default handler # mov word ptr [edi], bx ; write bits 15..0 of offset # mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT # mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present # mov word ptr [edi+6], ax ; write bits 31..16 of offset # add edi, 8 ; move up to next descriptor # loop @b ; loop back through again until all descriptors are initialized ## DUMP location of IDT and several of the descriptors # mov ecx, 8 # mov eax, [offset Idtr + 2] # mov eax, [eax] # mov edi, 0b8000h # call PrintDword # mov esi, eax # mov edi, 0b80a0h # jmp OuterLoop ## ## just for fun, let's do a software interrupt to see if we correctly land in the exception handler... # mov eax, 011111111h # mov ebx, 022222222h # mov ecx, 033333333h # mov edx, 044444444h # mov ebp, 055555555h # mov esi, 066666666h # mov edi, 077777777h # push 011111111h # push 022222222h # push 033333333h # int 119 movl $0x22000, %esi # esi = 22000 movl 0x14(%esi), %eax # eax = [22014] addl %eax, %esi # esi = 22000 + [22014] = Base of EFILDR.C movl 0x3c(%esi), %ebp # ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C addl %esi, %ebp movl 0x34(%ebp), %edi # edi = [[22000 + [22014] + 3c] + 30] = ImageBase movl 0x28(%ebp), %eax # eax = [[22000 + [22014] + 3c] + 24] = EntryPoint addl %edi, %eax # eax = ImageBase + EntryPoint movl %eax, EfiLdrOffset # Modify far jump instruction for correct entry point movw 6(%ebp), %bx # bx = Number of sections xorl %eax, %eax movw 0x14(%ebp), %ax # ax = Optional Header Size addl %eax, %ebp addl $0x18, %ebp # ebp = Start of 1st Section SectionLoop: pushl %esi # Save Base of EFILDR.C pushl %edi # Save ImageBase addl 0x14(%ebp), %esi # esi = Base of EFILDR.C + PointerToRawData addl 0x0c(%ebp), %edi # edi = ImageBase + VirtualAddress movl 0x10(%ebp), %ecx # ecs = SizeOfRawData cld shrl $2, %ecx rep movsl popl %edi # Restore ImageBase popl %esi # Restore Base of EFILDR.C addw $0x28, %bp # ebp = ebp + 028h = Pointer to next section record decw %bx cmpw $0, %bx jne SectionLoop movzwl (Idtr), %eax # get size of IDT incl %eax addl (Idtr + 2), %eax # add to base of IDT to get location of memory map... pushl %eax # push memory map location on stack for call to EFILDR... pushl %eax # push return address (useless, just for stack balance) .byte 0xb8 EfiLdrOffset: .long 0x00401000 # Offset of EFILDR # mov eax, 401000h pushl %eax ret # db "**** DEFAULT IDT ENTRY ***",0 .p2align 1 Halt: INT0: pushl $0x0 # push error code place holder on the stack pushl $0x0 jmpCommonIdtEntry # db 0e9h ; jmp 16 bit reletive # dd commonIdtEntry - $ - 4 ; offset to jump to INT1: pushl $0x0 # push error code place holder on the stack pushl $0x1 jmpCommonIdtEntry INT2: pushl $0x0 # push error code place holder on the stack pushl $0x2 jmpCommonIdtEntry INT3: pushl $0x0 # push error code place holder on the stack pushl $0x3 jmpCommonIdtEntry INT4: pushl $0x0 # push error code place holder on the stack pushl $0x4 jmpCommonIdtEntry INT5: pushl $0x0 # push error code place holder on the stack pushl $0x5 jmpCommonIdtEntry INT6: pushl $0x0 # push error code place holder on the stack pushl $0x6 jmpCommonIdtEntry INT7: pushl $0x0 # push error code place holder on the stack pushl $0x7 jmpCommonIdtEntry INT8: # Double fault causes an error code to be pushed so no phony push necessary nop nop pushl $0x8 jmpCommonIdtEntry INT9: pushl $0x0 # push error code place holder on the stack pushl $0x9 jmpCommonIdtEntry INT10: # Invalid TSS causes an error code to be pushed so no phony push necessary nop nop pushl $10 jmpCommonIdtEntry INT11: # Segment Not Present causes an error code to be pushed so no phony push necessary nop nop pushl $11 jmpCommonIdtEntry INT12: # Stack fault causes an error code to be pushed so no phony push necessary nop nop pushl $12 jmpCommonIdtEntry INT13: # GP fault causes an error code to be pushed so no phony push necessary nop nop pushl $13 jmpCommonIdtEntry INT14: # Page fault causes an error code to be pushed so no phony push necessary nop nop pushl $14 jmpCommonIdtEntry INT15: pushl $0x0 # push error code place holder on the stack pushl $15 jmpCommonIdtEntry INT16: pushl $0x0 # push error code place holder on the stack pushl $16 jmpCommonIdtEntry INT17: # Alignment check causes an error code to be pushed so no phony push necessary nop nop pushl $17 jmpCommonIdtEntry INT18: pushl $0x0 # push error code place holder on the stack pushl $18 jmpCommonIdtEntry INT19: pushl $0x0 # push error code place holder on the stack pushl $19 jmpCommonIdtEntry INTUnknown: .rept (0x78 - 20) pushl $0x0 # push error code place holder on the stack # push $0xxx # push vector number .byte 0x6a .long ( . - INTUnknown - 3 ) / 9 + 20 # vector number jmpCommonIdtEntry .endr commonIdtEntry: pushal movl %esp, %ebp ## ## At this point the stack looks like this: ## ## eflags ## Calling CS ## Calling EIP ## Error code or 0 ## Int num or 0ffh for unknown int num ## eax ## ecx ## edx ## ebx ## esp ## ebp ## esi ## edi <------- ESP, EBP ## call ClearScreen movl String1, %esi call PrintString movl 32(%ebp), %eax ## move Int number into EAX cmpl $19, %eax ja PrintDefaultString PrintExceptionString: shll $2, %eax ## multiply by 4 to get offset from StringTable to actual string address addl StringTable, %eax movl (%eax), %esi jmp PrintTheString PrintDefaultString: movl IntUnknownString, %esi # patch Int number movl %eax, %edx call A2C movb %al, 1(%esi) movl %edx, %eax shrl $4, %eax call A2C movb %al, (%esi) PrintTheString: call PrintString movl String2, %esi call PrintString movl 44(%ebp), %eax # CS call PrintDword movb ':', %al movb %al, (%edi) addl $2, %edi movl 40(%ebp), %eax # EIP call PrintDword movl String3, %esi call PrintString movl $0xb8140, %edi movl StringEax, %esi # eax call PrintString movl 28(%ebp), %eax call PrintDword movl StringEbx, %esi # ebx call PrintString movl 16(%ebp), %eax call PrintDword movl StringEcx, %esi # ecx call PrintString movl 24(%ebp), %eax call PrintDword movl StringEdx, %esi # edx call PrintString movl 20(%ebp), %eax call PrintDword movl StringEcode, %esi # error code call PrintString movl 36(%ebp), %eax call PrintDword movl $0xb81e0, %edi movl StringEsp, %esi # esp call PrintString movl 12(%ebp), %eax call PrintDword movl StringEbp, %esi # ebp call PrintString movl 8(%ebp), %eax call PrintDword movl StringEsi, %esi # esi call PrintString movl 4(%ebp), %eax call PrintDword movl StringEdi, %esi # edi call PrintString movl (%ebp), %eax call PrintDword movl StringEflags, %esi # eflags call PrintString movl 48(%ebp), %eax call PrintDword movl $0xb8320, %edi movl %ebp, %esi addl $52, %esi movl $8, %ecx OuterLoop: pushl %ecx movl $8, %ecx movl %edi, %edx InnerLoop: movl (%esi), %eax call PrintDword addl $4, %esi movb ' ', %al movb %al, (%edi) addl $2, %edi loop InnerLoop popl %ecx addl $0xa0, %edx movl %edx, %edi loop OuterLoop movl $0xb8960, %edi movl 40(%ebp), %eax # EIP subl $32*4, %eax movl %eax, %esi # esi = eip - 32 DWORD linear (total 64 DWORD) movl $8, %ecx OuterLoop1: pushl %ecx movl $8, %ecx movl %edi, %edx InnerLoop1: movl (%esi), %eax call PrintDword addl $4, %esi movb ' ', %al movb %al, (%edi) addl $2, %edi loop InnerLoop1 popl %ecx addl $0xa0, %edx movl %edx, %edi loop OuterLoop1 # wbinvd ; this intruction does not support in early than 486 arch LN_C1: jmp LN_C1 # # return # movl %ebp, %esp popal addl $8, %esp # error code and INT number iretl PrintString: pushl %eax LN_C2: movb (%esi), %al cmpb $0, %al je LN_C3 movb %al, (%edi) incl %esi addl $2, %edi jmp LN_C2 LN_C3: popl %eax ret ## EAX contains dword to print ## EDI contains memory location (screen location) to print it to PrintDword: pushl %ecx pushl %ebx pushl %eax movl $8, %ecx looptop: roll $4, %eax movb %al, %bl andb $0xf, %bl addb '0', %bl cmpb '9', %bl jle LN_C4 addb $7, %bl LN_C4: movb %bl, (%edi) addl $2, %edi loop looptop #wbinvd popl %eax popl %ebx popl %ecx ret ClearScreen: pushl %eax pushl %ecx movb $0x00, %al movb $0xc, %ah movl $0xb8000, %edi movl $80*24, %ecx LN_C5: movw %ax, (%edi) addl $2, %edi loop LN_C5 movl $0xb8000, %edi popl %ecx popl %eax ret A2C: andb $0xf, %al addb '0', %al cmpb '9', %al jle LN_C6 addb $7, %al LN_C6: ret String1: .asciz "*** INT " Int0String: .asciz "00h Divide by 0 -" Int1String: .asciz "01h Debug exception -" Int2String: .asciz "02h NMI -" Int3String: .asciz "03h Breakpoint -" Int4String: .asciz "04h Overflow -" Int5String: .asciz "05h Bound -" Int6String: .asciz "06h Invalid opcode -" Int7String: .asciz "07h Device not available -" Int8String: .asciz "08h Double fault -" Int9String: .asciz "09h Coprocessor seg overrun (reserved) -" Int10String: .asciz "0Ah Invalid TSS -" Int11String: .asciz "0Bh Segment not present -" Int12String: .asciz "0Ch Stack fault -" Int13String: .asciz "0Dh General protection fault -" Int14String: .asciz "0Eh Page fault -" Int15String: .asciz "0Fh (Intel reserved) -" Int16String: .asciz "10h Floating point error -" Int17String: .asciz "11h Alignment check -" Int18String: .asciz "12h Machine check -" Int19String: .asciz "13h SIMD Floating-Point Exception -" IntUnknownString: .asciz "??h Unknown interrupt -" StringTable: .long Int0String, Int1String, Int2String, Int3String, \ Int4String, Int5String, Int6String, Int7String, \ Int8String, Int9String, Int10String, Int11String, \ Int12String, Int13String, Int14String, Int15String,\ Int16String, Int17String, Int18String, Int19String String2: .asciz " HALT!! *** (" String3: .asciz ")" StringEax: .asciz "EAX=" StringEbx: .asciz "EBX=" StringEcx: .asciz "ECX=" StringEdx: .asciz "EDX=" StringEcode: .asciz "ECODE=" StringEsp: .asciz "ESP=" StringEbp: .asciz "EBP=" StringEsi: .asciz "ESI=" StringEdi: .asciz "EDI=" StringEflags: .asciz "EFLAGS=" Idtr: .float 0 .org 0x21ffe BlockSignature: .word 0xaa55