1 ;------------------------------------------------------------------------------ 2 ;* 3 ;* Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> 4 ;* This program and the accompanying materials 5 ;* are licensed and made available under the terms and conditions of the BSD License 6 ;* which accompanies this distribution. The full text of the license may be found at 7 ;* http://opensource.org/licenses/bsd-license.php 8 ;* 9 ;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 ;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 ;* 12 ;* efi32.asm 13 ;* 14 ;* Abstract: 15 ;* 16 ;------------------------------------------------------------------------------ 17 18 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 19 ; Now in 32-bit protected mode. 20 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21 22 .486 23 .model flat 24 .stack 25 .code 26 org 21000h 27 28 DEFAULT_HANDLER_SIZE EQU INT1 - INT0 29 30 JmpCommonIdtEntry macro 31 ; jmp commonIdtEntry - this must be hand coded to keep the assembler from 32 ; using a 8 bit reletive jump when the entries are 33 ; within 255 bytes of the common entry. This must 34 ; be done to maintain the consistency of the size 35 ; of entry points... 36 db 0e9h ; jmp 16 bit relative 37 dd commonIdtEntry - $ - 4 ; offset to jump to 38 endm 39 40 41 Start: 42 mov ax,bx ; flat data descriptor in BX 43 mov ds,ax 44 mov es,ax 45 mov fs,ax 46 mov gs,ax 47 mov ss,ax 48 mov esp,0001ffff0h 49 50 call ClearScreen 51 52 ; Populate IDT with meaningful offsets for exception handlers... 53 sidt fword ptr [Idtr] ; get fword address of IDT 54 55 mov eax, offset Halt 56 mov ebx, eax ; use bx to copy 15..0 to descriptors 57 shr eax, 16 ; use ax to copy 31..16 to descriptors 58 mov ecx, 78h ; 78h IDT entries to initialize with unique entry points (exceptions) 59 mov esi, [offset Idtr + 2] 60 mov edi, [esi] 61 62 @@: ; loop through all IDT entries exception handlers and initialize to default handler 63 mov word ptr [edi], bx ; write bits 15..0 of offset 64 mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT 65 mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present 66 mov word ptr [edi+6], ax ; write bits 31..16 of offset 67 add edi, 8 ; move up to next descriptor 68 add bx, DEFAULT_HANDLER_SIZE ; move to next entry point 69 loop @b ; loop back through again until all descriptors are initialized 70 71 ;; at this point edi contains the offset of the descriptor for INT 20 72 ;; and bx contains the low 16 bits of the offset of the default handler 73 ;; so initialize all the rest of the descriptors with these two values... 74 ; mov ecx, 101 ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h) 75 ;@@: ; loop through all IDT entries exception handlers and initialize to default handler 76 ; mov word ptr [edi], bx ; write bits 15..0 of offset 77 ; mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT 78 ; mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present 79 ; mov word ptr [edi+6], ax ; write bits 31..16 of offset 80 ; add edi, 8 ; move up to next descriptor 81 ; loop @b ; loop back through again until all descriptors are initialized 82 83 84 ;; DUMP location of IDT and several of the descriptors 85 ; mov ecx, 8 86 ; mov eax, [offset Idtr + 2] 87 ; mov eax, [eax] 88 ; mov edi, 0b8000h 89 ; call PrintDword 90 ; mov esi, eax 91 ; mov edi, 0b80a0h 92 ; jmp OuterLoop 93 94 ;; 95 ;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler... 96 ; mov eax, 011111111h 97 ; mov ebx, 022222222h 98 ; mov ecx, 033333333h 99 ; mov edx, 044444444h 100 ; mov ebp, 055555555h 101 ; mov esi, 066666666h 102 ; mov edi, 077777777h 103 ; push 011111111h 104 ; push 022222222h 105 ; push 033333333h 106 ; int 119 107 108 109 mov esi,022000h ; esi = 22000 110 mov eax,[esi+014h] ; eax = [22014] 111 add esi,eax ; esi = 22000 + [22014] = Base of EFILDR.C 112 mov ebp,[esi+03ch] ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C 113 add ebp,esi 114 mov edi,[ebp+034h] ; edi = [[22000 + [22014] + 3c] + 30] = ImageBase 115 mov eax,[ebp+028h] ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint 116 add eax,edi ; eax = ImageBase + EntryPoint 117 mov dword ptr [EfiLdrOffset],eax ; Modify far jump instruction for correct entry point 118 119 mov bx,word ptr[ebp+6] ; bx = Number of sections 120 xor eax,eax 121 mov ax,word ptr[ebp+014h] ; ax = Optional Header Size 122 add ebp,eax 123 add ebp,018h ; ebp = Start of 1st Section 124 125 SectionLoop: 126 push esi ; Save Base of EFILDR.C 127 push edi ; Save ImageBase 128 add esi,[ebp+014h] ; esi = Base of EFILDR.C + PointerToRawData 129 add edi,[ebp+00ch] ; edi = ImageBase + VirtualAddress 130 mov ecx,[ebp+010h] ; ecs = SizeOfRawData 131 132 cld 133 shr ecx,2 134 rep movsd 135 136 pop edi ; Restore ImageBase 137 pop esi ; Restore Base of EFILDR.C 138 139 add bp,028h ; ebp = ebp + 028h = Pointer to next section record 140 dec bx 141 cmp bx,0 142 jne SectionLoop 143 144 movzx eax, word ptr [Idtr] ; get size of IDT 145 inc eax 146 add eax, dword ptr [Idtr + 2] ; add to base of IDT to get location of memory map... 147 push eax ; push memory map location on stack for call to EFILDR... 148 149 push eax ; push return address (useless, just for stack balance) 150 db 0b8h 151 EfiLdrOffset: 152 dd 000401000h ; Offset of EFILDR 153 ; mov eax, 401000h 154 push eax 155 ret 156 157 ; db "**** DEFAULT IDT ENTRY ***",0 158 align 02h 159 Halt: 160 INT0: 161 push 0h ; push error code place holder on the stack 162 push 0h 163 JmpCommonIdtEntry 164 ; db 0e9h ; jmp 16 bit reletive 165 ; dd commonIdtEntry - $ - 4 ; offset to jump to 166 167 INT1: 168 push 0h ; push error code place holder on the stack 169 push 1h 170 JmpCommonIdtEntry 171 172 INT2: 173 push 0h ; push error code place holder on the stack 174 push 2h 175 JmpCommonIdtEntry 176 177 INT3: 178 push 0h ; push error code place holder on the stack 179 push 3h 180 JmpCommonIdtEntry 181 182 INT4: 183 push 0h ; push error code place holder on the stack 184 push 4h 185 JmpCommonIdtEntry 186 187 INT5: 188 push 0h ; push error code place holder on the stack 189 push 5h 190 JmpCommonIdtEntry 191 192 INT6: 193 push 0h ; push error code place holder on the stack 194 push 6h 195 JmpCommonIdtEntry 196 197 INT7: 198 push 0h ; push error code place holder on the stack 199 push 7h 200 JmpCommonIdtEntry 201 202 INT8: 203 ; Double fault causes an error code to be pushed so no phony push necessary 204 nop 205 nop 206 push 8h 207 JmpCommonIdtEntry 208 209 INT9: 210 push 0h ; push error code place holder on the stack 211 push 9h 212 JmpCommonIdtEntry 213 214 INT10: 215 ; Invalid TSS causes an error code to be pushed so no phony push necessary 216 nop 217 nop 218 push 10 219 JmpCommonIdtEntry 220 221 INT11: 222 ; Segment Not Present causes an error code to be pushed so no phony push necessary 223 nop 224 nop 225 push 11 226 JmpCommonIdtEntry 227 228 INT12: 229 ; Stack fault causes an error code to be pushed so no phony push necessary 230 nop 231 nop 232 push 12 233 JmpCommonIdtEntry 234 235 INT13: 236 ; GP fault causes an error code to be pushed so no phony push necessary 237 nop 238 nop 239 push 13 240 JmpCommonIdtEntry 241 242 INT14: 243 ; Page fault causes an error code to be pushed so no phony push necessary 244 nop 245 nop 246 push 14 247 JmpCommonIdtEntry 248 249 INT15: 250 push 0h ; push error code place holder on the stack 251 push 15 252 JmpCommonIdtEntry 253 254 INT16: 255 push 0h ; push error code place holder on the stack 256 push 16 257 JmpCommonIdtEntry 258 259 INT17: 260 ; Alignment check causes an error code to be pushed so no phony push necessary 261 nop 262 nop 263 push 17 264 JmpCommonIdtEntry 265 266 INT18: 267 push 0h ; push error code place holder on the stack 268 push 18 269 JmpCommonIdtEntry 270 271 INT19: 272 push 0h ; push error code place holder on the stack 273 push 19 274 JmpCommonIdtEntry 275 276 INTUnknown: 277 REPEAT (78h - 20) 278 push 0h ; push error code place holder on the stack 279 ; push xxh ; push vector number 280 db 06ah 281 db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number 282 JmpCommonIdtEntry 283 ENDM 284 285 commonIdtEntry: 286 pushad 287 mov ebp, esp 288 ;; 289 ;; At this point the stack looks like this: 290 ;; 291 ;; eflags 292 ;; Calling CS 293 ;; Calling EIP 294 ;; Error code or 0 295 ;; Int num or 0ffh for unknown int num 296 ;; eax 297 ;; ecx 298 ;; edx 299 ;; ebx 300 ;; esp 301 ;; ebp 302 ;; esi 303 ;; edi <------- ESP, EBP 304 ;; 305 306 call ClearScreen 307 mov esi, offset String1 308 call PrintString 309 mov eax, [ebp + 32] ;; move Int number into EAX 310 cmp eax, 19 311 ja PrintDefaultString 312 PrintExceptionString: 313 shl eax, 2 ;; multiply by 4 to get offset from StringTable to actual string address 314 add eax, offset StringTable 315 mov esi, [eax] 316 jmp PrintTheString 317 PrintDefaultString: 318 mov esi, offset IntUnknownString 319 ; patch Int number 320 mov edx, eax 321 call A2C 322 mov [esi + 1], al 323 mov eax, edx 324 shr eax, 4 325 call A2C 326 mov [esi], al 327 PrintTheString: 328 call PrintString 329 mov esi, offset String2 330 call PrintString 331 mov eax, [ebp+44] ; CS 332 call PrintDword 333 mov al, ':' 334 mov byte ptr [edi], al 335 add edi, 2 336 mov eax, [ebp+40] ; EIP 337 call PrintDword 338 mov esi, offset String3 339 call PrintString 340 341 mov edi, 0b8140h 342 343 mov esi, offset StringEax ; eax 344 call PrintString 345 mov eax, [ebp+28] 346 call PrintDword 347 348 mov esi, offset StringEbx ; ebx 349 call PrintString 350 mov eax, [ebp+16] 351 call PrintDword 352 353 mov esi, offset StringEcx ; ecx 354 call PrintString 355 mov eax, [ebp+24] 356 call PrintDword 357 358 mov esi, offset StringEdx ; edx 359 call PrintString 360 mov eax, [ebp+20] 361 call PrintDword 362 363 mov esi, offset StringEcode ; error code 364 call PrintString 365 mov eax, [ebp+36] 366 call PrintDword 367 368 mov edi, 0b81e0h 369 370 mov esi, offset StringEsp ; esp 371 call PrintString 372 mov eax, [ebp+12] 373 call PrintDword 374 375 mov esi, offset StringEbp ; ebp 376 call PrintString 377 mov eax, [ebp+8] 378 call PrintDword 379 380 mov esi, offset StringEsi ; esi 381 call PrintString 382 mov eax, [ebp+4] 383 call PrintDword 384 385 mov esi, offset StringEdi ; edi 386 call PrintString 387 mov eax, [ebp] 388 call PrintDword 389 390 mov esi, offset StringEflags ; eflags 391 call PrintString 392 mov eax, [ebp+48] 393 call PrintDword 394 395 mov edi, 0b8320h 396 397 mov esi, ebp 398 add esi, 52 399 mov ecx, 8 400 401 402 OuterLoop: 403 push ecx 404 mov ecx, 8 405 mov edx, edi 406 407 InnerLoop: 408 mov eax, [esi] 409 call PrintDword 410 add esi, 4 411 mov al, ' ' 412 mov [edi], al 413 add edi, 2 414 loop InnerLoop 415 416 pop ecx 417 add edx, 0a0h 418 mov edi, edx 419 loop OuterLoop 420 421 422 mov edi, 0b8960h 423 424 mov eax, [ebp+40] ; EIP 425 sub eax, 32 * 4 426 mov esi, eax ; esi = eip - 32 DWORD linear (total 64 DWORD) 427 428 mov ecx, 8 429 430 OuterLoop1: 431 push ecx 432 mov ecx, 8 433 mov edx, edi 434 435 InnerLoop1: 436 mov eax, [esi] 437 call PrintDword 438 add esi, 4 439 mov al, ' ' 440 mov [edi], al 441 add edi, 2 442 loop InnerLoop1 443 444 pop ecx 445 add edx, 0a0h 446 mov edi, edx 447 loop OuterLoop1 448 449 450 451 ; wbinvd ; Ken: this intruction does not support in early than 486 arch 452 @@: 453 jmp @b 454 ; 455 ; return 456 ; 457 mov esp, ebp 458 popad 459 add esp, 8 ; error code and INT number 460 461 iretd 462 463 464 PrintString: 465 push eax 466 @@: 467 mov al, byte ptr [esi] 468 cmp al, 0 469 je @f 470 mov byte ptr [edi], al 471 inc esi 472 add edi, 2 473 jmp @b 474 @@: 475 pop eax 476 ret 477 478 ;; EAX contains dword to print 479 ;; EDI contains memory location (screen location) to print it to 480 PrintDword: 481 push ecx 482 push ebx 483 push eax 484 485 mov ecx, 8 486 looptop: 487 rol eax, 4 488 mov bl, al 489 and bl, 0fh 490 add bl, '0' 491 cmp bl, '9' 492 jle @f 493 add bl, 7 494 @@: 495 mov byte ptr [edi], bl 496 add edi, 2 497 loop looptop 498 ;wbinvd 499 500 pop eax 501 pop ebx 502 pop ecx 503 ret 504 505 ClearScreen: 506 push eax 507 push ecx 508 509 mov al, ' ' 510 mov ah, 0ch 511 mov edi, 0b8000h 512 mov ecx, 80 * 24 513 @@: 514 mov word ptr [edi], ax 515 add edi, 2 516 loop @b 517 mov edi, 0b8000h 518 519 pop ecx 520 pop eax 521 522 ret 523 524 A2C: 525 and al, 0fh 526 add al, '0' 527 cmp al, '9' 528 jle @f 529 add al, 7 530 @@: 531 ret 532 533 String1 db "*** INT ",0 534 535 Int0String db "00h Divide by 0 -",0 536 Int1String db "01h Debug exception -",0 537 Int2String db "02h NMI -",0 538 Int3String db "03h Breakpoint -",0 539 Int4String db "04h Overflow -",0 540 Int5String db "05h Bound -",0 541 Int6String db "06h Invalid opcode -",0 542 Int7String db "07h Device not available -",0 543 Int8String db "08h Double fault -",0 544 Int9String db "09h Coprocessor seg overrun (reserved) -",0 545 Int10String db "0Ah Invalid TSS -",0 546 Int11String db "0Bh Segment not present -",0 547 Int12String db "0Ch Stack fault -",0 548 Int13String db "0Dh General protection fault -",0 549 Int14String db "0Eh Page fault -",0 550 Int15String db "0Fh (Intel reserved) -",0 551 Int16String db "10h Floating point error -",0 552 Int17String db "11h Alignment check -",0 553 Int18String db "12h Machine check -",0 554 Int19String db "13h SIMD Floating-Point Exception -",0 555 IntUnknownString db "??h Unknown interrupt -",0 556 557 StringTable dd offset Int0String, offset Int1String, offset Int2String, offset Int3String, 558 offset Int4String, offset Int5String, offset Int6String, offset Int7String, 559 offset Int8String, offset Int9String, offset Int10String, offset Int11String, 560 offset Int12String, offset Int13String, offset Int14String, offset Int15String, 561 offset Int16String, offset Int17String, offset Int18String, offset Int19String 562 563 String2 db " HALT!! *** (",0 564 String3 db ")",0 565 StringEax db "EAX=",0 566 StringEbx db " EBX=",0 567 StringEcx db " ECX=",0 568 StringEdx db " EDX=",0 569 StringEcode db " ECODE=",0 570 StringEsp db "ESP=",0 571 StringEbp db " EBP=",0 572 StringEsi db " ESI=",0 573 StringEdi db " EDI=",0 574 StringEflags db " EFLAGS=",0 575 576 Idtr df 0 577 578 org 21ffeh 579 BlockSignature: 580 dw 0aa55h 581 582 end 583