| #------------------------------------------------------------------------------ |
| #* |
| #* 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. |
| #* |
| #* efi64.asm |
| #* |
| #* Abstract: |
| #* |
| #------------------------------------------------------------------------------ |
| |
| ############################################################################## |
| # Now in 64-bit long mode. |
| ############################################################################## |
| |
| .486: |
| .stack: |
| .code: |
| .org 0x21000 |
| |
| .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: |
| |
| movl $0x001fffe8,%esp # make final stack aligned |
| |
| # set OSFXSR and OSXMMEXCPT because some code will use XMM register |
| .byte 0xf |
| .byte 0x20 |
| .byte 0xe0 |
| # mov rax, cr4 |
| btsl $9,%eax |
| btsl $0xa,%eax |
| .byte 0xf |
| .byte 0x22 |
| .byte 0xe0 |
| # mov cr4, rax |
| |
| 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 |
| # 63..32 of descriptors is 0 |
| 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 $0x38, 2(%edi) # SYS_CODE_SEL64 from GDT
|
| movw $(0x0e00 | 0x8000), 4(%edi) # type = 386 interrupt gate, present
|
| movw %ax, 6(%edi) # write bits 31..16 of offset |
| movl $0, 8(%edi) # write bits 31..16 of offset
|
| addl $16, %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], 38h ; SYS_CODE64_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 |
| # mov dword ptr [edi+8], 0 ; write bits 63..32 of offset |
| # add edi, 16 ; 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 PrintQword |
| # 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 0x30(%ebp),%edi # edi = [[22000 + [22014] + 3c] + 2c] = ImageBase (63..32 is zero, ignore) |
| movl 0x28(%ebp),%eax # eax = [[22000 + [22014] + 3c] + 24] = EntryPoint |
| addl %edi,%eax # eax = ImageBase + EntryPoint |
| movl %ebx, EfiLdrOffset |
| movl %eax, (%ebx) # 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 |
| .byte 0x66 |
| .byte 0xff |
| .byte 0xcb |
| # dec bx |
| cmpw $0,%bx |
| jne SectionLoop |
| |
| movl (Idtr), %eax # get size of IDT |
| movzx (%edx), %eax |
| .byte 0xff |
| .byte 0xc0 |
| # inc eax |
| addl 2(%edx), %eax # add to base of IDT to get location of memory map... |
| xorl %ecx,%ecx |
| movl %eax,%ecx # put argument to RCX |
| |
| .byte 0x48 |
| .byte 0xc7 |
| .byte 0xc0 |
| EfiLdrOffset: |
| .long 0x00401000 # Offset of EFILDR |
| # mov rax, 401000h |
| .byte 0x50 |
| # push rax |
| |
| # ret |
| .byte 0xc3 |
| |
| # 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 xxh ; push vector number |
| .byte 0x6a |
| .byte ( . - INTUnknown - 3 ) / 9 + 20 # vector number |
| jmpCommonIdtEntry |
| .endr |
| |
| commonIdtEntry: |
| pushl %eax |
| pushl %ecx |
| pushl %edx |
| pushl %ebx |
| pushl %esp |
| pushl %ebp |
| pushl %esi |
| pushl %edi |
| .byte 0x41 |
| .byte 0x50 |
| # push r8 |
| .byte 0x41 |
| .byte 0x51 |
| # push r9 |
| .byte 0x41 |
| .byte 0x52 |
| # push r10 |
| .byte 0x41 |
| .byte 0x53 |
| # push r11 |
| .byte 0x41 |
| .byte 0x54 |
| # push r12 |
| .byte 0x41 |
| .byte 0x55 |
| # push r13 |
| .byte 0x41 |
| .byte 0x56 |
| # push r14 |
| .byte 0x41 |
| .byte 0x57 |
| # push r15 |
| .byte 0x48 |
| movl %esp,%ebp |
| # mov rbp, rsp |
| |
| ## |
| ## At this point the stack looks like this: |
| ## |
| ## Calling SS |
| ## Calling RSP |
| ## rflags |
| ## Calling CS |
| ## Calling RIP |
| ## Error code or 0 |
| ## Int num or 0ffh for unknown int num |
| ## rax |
| ## rcx |
| ## rdx |
| ## rbx |
| ## rsp |
| ## rbp |
| ## rsi |
| ## rdi |
| ## r8 |
| ## r9 |
| ## r10 |
| ## r11 |
| ## r12 |
| ## r13 |
| ## r14 |
| ## r15 <------- RSP, RBP |
| ## |
| |
| call ClearScreen |
| mov String1, %esi |
| call PrintString |
| .byte 0x48 |
| movl 16*8(%ebp),%eax ## move Int number into RAX |
| .byte 0x48 |
| cmpl $18,%eax |
| ja PrintDefaultString |
| PrintExceptionString: |
| shll $3,%eax ## multiply by 8 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 |
| .byte 0x48 |
| movl 19*8(%ebp),%eax # CS |
| call PrintQword |
| movb $':', %al |
| movb %al, (%edi) |
| addl $2,%edi |
| .byte 0x48 |
| movl 18*8(%ebp),%eax # RIP |
| call PrintQword |
| movl String3, %esi |
| call PrintString |
| |
| movl $0xb8140,%edi |
| |
| movl StringRax, %esi |
| call PrintString |
| .byte 0x48 |
| movl 15*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringRcx, %esi |
| call PrintString |
| .byte 0x48 |
| movl 14*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringRdx, %esi |
| call PrintString |
| .byte 0x48 |
| movl 13*8(%ebp),%eax |
| call PrintQword |
| |
| movl $0xb81e0,%edi |
| |
| movl StringRbx, %esi |
| call PrintString |
| .byte 0x48 |
| movl 12*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringRsp, %esi |
| call PrintString |
| .byte 0x48 |
| movl 21*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringRbp, %esi |
| call PrintString |
| .byte 0x48 |
| movl 10*8(%ebp),%eax |
| call PrintQword |
| |
| movl $0xb8280,%edi |
| |
| movl StringRsi, %esi |
| call PrintString |
| .byte 0x48 |
| movl 9*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringRdi, %esi |
| call PrintString |
| .byte 0x48 |
| movl 8*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringEcode, %esi |
| call PrintString |
| .byte 0x48 |
| movl 17*8(%ebp),%eax |
| call PrintQword |
| |
| movl $0xb8320,%edi |
| |
| movl StringR8, %esi |
| call PrintString |
| .byte 0x48 |
| movl 7*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringR9, %esi |
| call PrintString |
| .byte 0x48 |
| movl 6*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringR10, %esi |
| call PrintString |
| .byte 0x48 |
| movl 5*8(%ebp),%eax |
| call PrintQword |
| |
| movl $0xb83c0,%edi |
| |
| movl StringR11, %esi |
| call PrintString |
| .byte 0x48 |
| movl 4*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringR12, %esi |
| call PrintString |
| .byte 0x48 |
| movl 3*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringR13, %esi |
| call PrintString |
| .byte 0x48 |
| movl 2*8(%ebp),%eax |
| call PrintQword |
| |
| movl $0xb8460,%edi |
| |
| movl StringR14, %esi |
| call PrintString |
| .byte 0x48 |
| movl 1*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringR15, %esi |
| call PrintString |
| .byte 0x48 |
| movl 0*8(%ebp),%eax |
| call PrintQword |
| |
| movl StringSs, %esi |
| call PrintString |
| .byte 0x48 |
| movl 22*8(%ebp),%eax |
| call PrintQword |
| |
| movl $0xb8500,%edi |
| |
| movl StringRflags, %esi |
| call PrintString |
| .byte 0x48 |
| movl 20*8(%ebp),%eax |
| call PrintQword |
| |
| movl $0xb8640,%edi |
| |
| movl %ebp,%esi |
| addl $23*8,%esi |
| movl $4,%ecx |
| |
| |
| OuterLoop: |
| pushl %ecx |
| movl $4,%ecx |
| .byte 0x48 |
| movl %edi,%edx |
| |
| InnerLoop: |
| .byte 0x48 |
| movl (%esi),%eax |
| call PrintQword |
| addl $8,%esi |
| mov $0x00, %al |
| movb %al,(%edi) |
| addl $2,%edi |
| loop InnerLoop |
| |
| popl %ecx |
| addl $0xa0,%edx |
| movl %edx,%edi |
| loop OuterLoop |
| |
| |
| movl $0xb8960,%edi |
| |
| .byte 0x48 |
| movl 18*8(%ebp),%eax # RIP |
| subl $8*8,%eax |
| .byte 0x48 |
| movl %eax,%esi # esi = rip - 8 QWORD linear (total 16 QWORD) |
| |
| movl $4,%ecx |
| |
| OuterLoop1: |
| pushl %ecx |
| movl $4,%ecx |
| movl %edi,%edx |
| |
| InnerLoop1: |
| .byte 0x48 |
| movl (%esi),%eax |
| call PrintQword |
| addl $8,%esi |
| movb $0x00, %al |
| movb %al,(%edi) |
| addl $2,%edi |
| loop InnerLoop1 |
| |
| popl %ecx |
| addl $0xa0,%edx |
| movl %edx,%edi |
| loop OuterLoop1 |
| |
| |
| |
| #wbinvd |
| LN_C1:
|
| jmp LN_C1 |
| |
| # |
| # return |
| # |
| movl %ebp,%esp |
| # mov rsp, rbp |
| .byte 0x41 |
| .byte 0x5f |
| # pop r15 |
| .byte 0x41 |
| .byte 0x5e |
| # pop r14 |
| .byte 0x41 |
| .byte 0x5d |
| # pop r13 |
| .byte 0x41 |
| .byte 0x5c |
| # pop r12 |
| .byte 0x41 |
| .byte 0x5b |
| # pop r11 |
| .byte 0x41 |
| .byte 0x5a |
| # pop r10 |
| .byte 0x41 |
| .byte 0x59 |
| # pop r9 |
| .byte 0x41 |
| .byte 0x58 |
| # pop r8 |
| popl %edi |
| popl %esi |
| popl %ebp |
| popl %eax # esp |
| popl %ebx |
| popl %edx |
| popl %ecx |
| popl %eax |
| |
| .byte 0x48 |
| .byte 0x83 |
| .byte 0xc4 |
| .byte 0x10 |
| # add esp, 16 ; error code and INT number |
| |
| .byte 0x48 |
| .byte 0xcf |
| # iretq |
| |
| PrintString: |
| pushl %eax |
| LN_C2: |
| movb (%esi), %al |
| cmpb $0,%al |
| je LN_C3 |
| movb %al, (%edi) |
| .byte 0xff |
| .byte 0xc6 |
| # inc esi |
| addl $2,%edi |
| jmp LN_C2 |
| LN_C3: |
| popl %eax |
| ret |
| |
| ## RAX contains qword to print |
| ## RDI contains memory location (screen location) to print it to |
| PrintQword: |
| pushl %ecx |
| pushl %ebx |
| pushl %eax |
| |
| .byte 0x48 |
| .byte 0xc7 |
| .byte 0xc1 |
| .long 16 |
| # mov rcx, 16 |
| looptop: |
| .byte 0x48 |
| roll $4,%eax |
| movb %al,%bl |
| andb $0xf,%bl |
| addb $'0', %bl |
| cmpb $'9', %bl |
| jle @f |
| addb $7,%bl |
| @@: |
| 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_C4: |
| movw %ax, (%edi) |
| addl $2,%edi |
| loop LN_C4 |
| movl $0xb8000,%edi |
| |
| popl %ecx |
| popl %eax |
| |
| ret |
| |
| A2C: |
| andb $0xf,%al |
| addb $'0', %al |
| cmpb $'9', %al |
| jle @f |
| addb $7,%al |
| LN_C5: |
| 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 ")" |
| StringRax: .asciz "RAX=" |
| StringRcx: .asciz " RCX=" |
| StringRdx: .asciz " RDX=" |
| StringRbx: .asciz "RBX=" |
| StringRsp: .asciz " RSP=" |
| StringRbp: .asciz " RBP=" |
| StringRsi: .asciz "RSI=" |
| StringRdi: .asciz " RDI=" |
| StringEcode: .asciz " ECODE=" |
| StringR8: .asciz "R8 =" |
| StringR9: .asciz " R9 =" |
| StringR10: .asciz " R10=" |
| StringR11: .asciz "R11=" |
| StringR12: .asciz " R12=" |
| StringR13: .asciz " R13=" |
| StringR14: .asciz "R14=" |
| StringR15: .asciz " R15=" |
| StringSs: .asciz " SS =" |
| StringRflags: .asciz "RFLAGS=" |
| |
| Idtr: .float 0 |
| .float 0 |
| |
| .org 0x21ffe |
| BlockSignature: |
| .word 0xaa55 |
| |