| #------------------------------------------------------------------------------
|
| #*
|
| #* 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
|
| .align 0x2
|
| 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
|
|
|
|
|