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        
28DEFAULT_HANDLER_SIZE EQU INT1 - INT0
29
30JmpCommonIdtEntry  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
38endm    
39
40        
41Start:  
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
125SectionLoop:
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
151EfiLdrOffset:
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
159Halt:
160INT0:
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    
167INT1:
168    push    0h      ; push error code place holder on the stack
169    push    1h
170    JmpCommonIdtEntry
171    
172INT2:
173    push    0h      ; push error code place holder on the stack
174    push    2h
175    JmpCommonIdtEntry
176    
177INT3:
178    push    0h      ; push error code place holder on the stack
179    push    3h
180    JmpCommonIdtEntry
181    
182INT4:
183    push    0h      ; push error code place holder on the stack
184    push    4h
185    JmpCommonIdtEntry
186    
187INT5:
188    push    0h      ; push error code place holder on the stack
189    push    5h
190    JmpCommonIdtEntry
191    
192INT6:
193    push    0h      ; push error code place holder on the stack
194    push    6h
195    JmpCommonIdtEntry
196    
197INT7:
198    push    0h      ; push error code place holder on the stack
199    push    7h
200    JmpCommonIdtEntry
201    
202INT8:
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    
209INT9:
210    push    0h      ; push error code place holder on the stack
211    push    9h
212    JmpCommonIdtEntry
213    
214INT10:
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    
221INT11:
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    
228INT12:
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    
235INT13:
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    
242INT14:
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    
249INT15:
250    push    0h      ; push error code place holder on the stack
251    push    15
252    JmpCommonIdtEntry
253    
254INT16:
255    push    0h      ; push error code place holder on the stack
256    push    16
257    JmpCommonIdtEntry
258    
259INT17:
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    
266INT18:
267    push    0h      ; push error code place holder on the stack
268    push    18
269    JmpCommonIdtEntry
270    
271INT19:
272    push    0h      ; push error code place holder on the stack
273    push    19
274    JmpCommonIdtEntry
275
276INTUnknown:
277REPEAT  (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
283ENDM
284
285commonIdtEntry:
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
312PrintExceptionString:
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
317PrintDefaultString:
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
327PrintTheString:        
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    
402OuterLoop:
403    push    ecx
404    mov     ecx, 8
405    mov     edx, edi
406
407InnerLoop:
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    
430OuterLoop1:
431    push    ecx
432    mov     ecx, 8
433    mov     edx, edi
434
435InnerLoop1:
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
464PrintString:
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
480PrintDword:
481    push    ecx
482    push    ebx
483    push    eax
484    
485    mov     ecx, 8
486looptop:
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
505ClearScreen:
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        
524A2C:
525    and     al, 0fh
526    add     al, '0'
527    cmp     al, '9'
528    jle     @f
529    add     al, 7
530@@:
531    ret
532        
533String1           db  "*** INT ",0
534
535Int0String        db  "00h Divide by 0 -",0
536Int1String        db  "01h Debug exception -",0
537Int2String        db  "02h NMI -",0
538Int3String        db  "03h Breakpoint -",0
539Int4String        db  "04h Overflow -",0
540Int5String        db  "05h Bound -",0
541Int6String        db  "06h Invalid opcode -",0
542Int7String        db  "07h Device not available -",0
543Int8String        db  "08h Double fault -",0
544Int9String        db  "09h Coprocessor seg overrun (reserved) -",0
545Int10String       db  "0Ah Invalid TSS -",0
546Int11String       db  "0Bh Segment not present -",0
547Int12String       db  "0Ch Stack fault -",0
548Int13String       db  "0Dh General protection fault -",0
549Int14String       db  "0Eh Page fault -",0
550Int15String       db  "0Fh (Intel reserved) -",0
551Int16String       db  "10h Floating point error -",0
552Int17String       db  "11h Alignment check -",0
553Int18String       db  "12h Machine check -",0
554Int19String       db  "13h SIMD Floating-Point Exception -",0
555IntUnknownString  db  "??h Unknown interrupt -",0
556
557StringTable       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
563String2           db  " HALT!! *** (",0
564String3           db  ")",0
565StringEax         db  "EAX=",0
566StringEbx         db  " EBX=",0
567StringEcx         db  " ECX=",0
568StringEdx         db  " EDX=",0
569StringEcode       db  " ECODE=",0
570StringEsp         db  "ESP=",0
571StringEbp         db  " EBP=",0
572StringEsi         db  " ESI=",0
573StringEdi         db  " EDI=",0
574StringEflags      db  " EFLAGS=",0
575
576Idtr        df  0
577
578    org 21ffeh
579BlockSignature:
580    dw      0aa55h
581    
582    end
583