1;------------------------------------------------------------------------------
2;*
3;*   Copyright (c) 2006, 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;*    efi64.asm
13;*  
14;*   Abstract:
15;*
16;------------------------------------------------------------------------------
17
18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19; Now in 64-bit long 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 reletive 
37    dd      commonIdtEntry - $ - 4      ;  offset to jump to
38endm    
39
40        
41Start:  
42
43    mov     esp,0001fffe8h ; make final stack aligned
44
45    ; set OSFXSR and OSXMMEXCPT because some code will use XMM register
46    db 0fh
47    db 20h
48    db 0e0h
49;    mov rax, cr4
50    bts eax, 9
51    bts eax, 0ah
52    db 0fh
53    db 22h
54    db 0e0h
55;    mov cr4, rax
56
57    call    ClearScreen
58
59    ; Populate IDT with meaningful offsets for exception handlers...
60    mov     eax, offset Idtr
61    sidt    fword ptr [eax]             ; get fword address of IDT
62
63    mov     eax, offset Halt
64    mov     ebx, eax                    ; use bx to copy 15..0 to descriptors
65    shr     eax, 16                     ; use ax to copy 31..16 to descriptors 
66                                        ; 63..32 of descriptors is 0
67    mov     ecx, 78h                    ; 78h IDT entries to initialize with unique entry points (exceptions)
68    mov     esi, [offset Idtr + 2]
69    mov     edi, [esi]
70
71@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler
72    mov     word ptr [edi], bx                  ; write bits 15..0 of offset
73    mov     word ptr [edi+2], 38h               ; SYS_CODE64_SEL from GDT
74    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present
75    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset
76    mov     dword ptr [edi+8], 0                ; write bits 63..32 of offset
77    add     edi, 16                             ; move up to next descriptor
78    add     bx, DEFAULT_HANDLER_SIZE            ; move to next entry point
79    loop    @b                                  ; loop back through again until all descriptors are initialized
80    
81    ;; at this point edi contains the offset of the descriptor for INT 20
82    ;; and bx contains the low 16 bits of the offset of the default handler
83    ;; so initialize all the rest of the descriptors with these two values...
84;    mov     ecx, 101                            ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)
85;@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler
86;    mov     word ptr [edi], bx                  ; write bits 15..0 of offset
87;    mov     word ptr [edi+2], 38h               ; SYS_CODE64_SEL from GDT
88;    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present
89;    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset
90;    mov     dword ptr [edi+8], 0                ; write bits 63..32 of offset
91;    add     edi, 16                             ; move up to next descriptor
92;    loop    @b                                  ; loop back through again until all descriptors are initialized
93    
94    
95;;  DUMP    location of IDT and several of the descriptors
96;    mov     ecx, 8
97;    mov     eax, [offset Idtr + 2]
98;    mov     eax, [eax]
99;    mov     edi, 0b8000h
100;    call    PrintQword
101;    mov     esi, eax
102;    mov     edi, 0b80a0h
103;    jmp     OuterLoop
104    
105;;    
106;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...
107;    mov     eax, 011111111h
108;    mov     ebx, 022222222h
109;    mov     ecx, 033333333h
110;    mov     edx, 044444444h
111;    mov     ebp, 055555555h
112;    mov     esi, 066666666h
113;    mov     edi, 077777777h
114;    push    011111111h
115;    push    022222222h
116;    push    033333333h
117;    int     119
118
119    mov     esi,022000h                 ; esi = 22000
120    mov     eax,[esi+014h]              ; eax = [22014]
121    add     esi,eax                     ; esi = 22000 + [22014] = Base of EFILDR.C
122    mov     ebp,[esi+03ch]              ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C
123    add     ebp,esi
124    mov     edi,[ebp+030h]              ; edi = [[22000 + [22014] + 3c] + 2c] = ImageBase (63..32 is zero, ignore)
125    mov     eax,[ebp+028h]              ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint
126    add     eax,edi                     ; eax = ImageBase + EntryPoint
127    mov     ebx, offset EfiLdrOffset
128    mov     dword ptr [ebx],eax         ; Modify far jump instruction for correct entry point
129
130    mov     bx,word ptr[ebp+6]          ; bx = Number of sections
131    xor     eax,eax
132    mov     ax,word ptr[ebp+014h]       ; ax = Optional Header Size
133    add     ebp,eax
134    add     ebp,018h                    ; ebp = Start of 1st Section
135
136SectionLoop:
137    push    esi                         ; Save Base of EFILDR.C
138    push    edi                         ; Save ImageBase
139    add     esi,[ebp+014h]              ; esi = Base of EFILDR.C + PointerToRawData
140    add     edi,[ebp+00ch]              ; edi = ImageBase + VirtualAddress
141    mov     ecx,[ebp+010h]              ; ecs = SizeOfRawData
142
143    cld
144    shr     ecx,2
145    rep     movsd
146
147    pop     edi                         ; Restore ImageBase
148    pop     esi                         ; Restore Base of EFILDR.C
149
150    add     bp,028h                     ; ebp = ebp + 028h = Pointer to next section record
151    db 66h
152    db 0ffh
153    db 0cbh
154;    dec     bx
155    cmp     bx,0
156    jne     SectionLoop
157
158    mov     edx, offset Idtr
159    movzx   eax, word ptr [edx]          ; get size of IDT
160    db 0ffh
161    db 0c0h
162;    inc     eax
163    add     eax, dword ptr [edx + 2]     ; add to base of IDT to get location of memory map...
164    xor     ecx, ecx
165    mov     ecx, eax                     ; put argument to RCX
166
167    db 48h
168    db 0c7h
169    db 0c0h
170EfiLdrOffset:
171    dd      000401000h                  ; Offset of EFILDR
172;   mov rax, 401000h
173    db 50h
174;   push rax
175
176; ret
177    db 0c3h
178
179;    db      "**** DEFAULT IDT ENTRY ***",0
180    align 02h
181Halt:
182INT0:
183    push    0h      ; push error code place holder on the stack
184    push    0h
185    JmpCommonIdtEntry
186;    db      0e9h                        ; jmp 16 bit reletive 
187;    dd      commonIdtEntry - $ - 4      ;  offset to jump to
188    
189INT1:
190    push    0h      ; push error code place holder on the stack
191    push    1h
192    JmpCommonIdtEntry
193    
194INT2:
195    push    0h      ; push error code place holder on the stack
196    push    2h
197    JmpCommonIdtEntry
198    
199INT3:
200    push    0h      ; push error code place holder on the stack
201    push    3h
202    JmpCommonIdtEntry
203    
204INT4:
205    push    0h      ; push error code place holder on the stack
206    push    4h
207    JmpCommonIdtEntry
208    
209INT5:
210    push    0h      ; push error code place holder on the stack
211    push    5h
212    JmpCommonIdtEntry
213    
214INT6:
215    push    0h      ; push error code place holder on the stack
216    push    6h
217    JmpCommonIdtEntry
218    
219INT7:
220    push    0h      ; push error code place holder on the stack
221    push    7h
222    JmpCommonIdtEntry
223    
224INT8:
225;   Double fault causes an error code to be pushed so no phony push necessary
226    nop
227    nop
228    push    8h
229    JmpCommonIdtEntry
230    
231INT9:
232    push    0h      ; push error code place holder on the stack
233    push    9h
234    JmpCommonIdtEntry
235    
236INT10:
237;   Invalid TSS causes an error code to be pushed so no phony push necessary
238    nop
239    nop
240    push    10
241    JmpCommonIdtEntry
242    
243INT11:
244;   Segment Not Present causes an error code to be pushed so no phony push necessary
245    nop
246    nop
247    push    11
248    JmpCommonIdtEntry
249    
250INT12:
251;   Stack fault causes an error code to be pushed so no phony push necessary
252    nop
253    nop
254    push    12
255    JmpCommonIdtEntry
256    
257INT13:
258;   GP fault causes an error code to be pushed so no phony push necessary
259    nop
260    nop
261    push    13
262    JmpCommonIdtEntry
263    
264INT14:
265;   Page fault causes an error code to be pushed so no phony push necessary
266    nop
267    nop
268    push    14
269    JmpCommonIdtEntry
270    
271INT15:
272    push    0h      ; push error code place holder on the stack
273    push    15
274    JmpCommonIdtEntry
275    
276INT16:
277    push    0h      ; push error code place holder on the stack
278    push    16
279    JmpCommonIdtEntry
280    
281INT17:
282;   Alignment check causes an error code to be pushed so no phony push necessary
283    nop
284    nop
285    push    17
286    JmpCommonIdtEntry
287    
288INT18:
289    push    0h      ; push error code place holder on the stack
290    push    18
291    JmpCommonIdtEntry
292    
293INT19:
294    push    0h      ; push error code place holder on the stack
295    push    19
296    JmpCommonIdtEntry
297
298INTUnknown:
299REPEAT  (78h - 20)
300    push    0h      ; push error code place holder on the stack
301;    push    xxh     ; push vector number
302    db      06ah
303    db      ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
304    JmpCommonIdtEntry
305ENDM
306
307commonIdtEntry:
308    push    eax
309    push    ecx
310    push    edx
311    push    ebx
312    push    esp
313    push    ebp
314    push    esi
315    push    edi
316    db 41h
317    db 50h
318;    push    r8
319    db 41h
320    db 51h
321;    push    r9
322    db 41h
323    db 52h
324;    push    r10
325    db 41h
326    db 53h
327;    push    r11
328    db 41h
329    db 54h
330;    push    r12
331    db 41h
332    db 55h
333;    push    r13
334    db 41h
335    db 56h
336;    push    r14
337    db 41h
338    db 57h
339;    push    r15
340    db 48h
341    mov     ebp, esp
342;    mov     rbp, rsp
343
344;;
345;;  At this point the stack looks like this:
346;;
347;;      Calling SS
348;;      Calling RSP
349;;      rflags
350;;      Calling CS
351;;      Calling RIP
352;;      Error code or 0
353;;      Int num or 0ffh for unknown int num
354;;      rax
355;;      rcx
356;;      rdx
357;;      rbx
358;;      rsp
359;;      rbp
360;;      rsi
361;;      rdi
362;;      r8
363;;      r9
364;;      r10
365;;      r11
366;;      r12
367;;      r13
368;;      r14
369;;      r15 <------- RSP, RBP
370;;      
371
372    call    ClearScreen
373    mov     esi, offset String1
374    call    PrintString
375    db 48h
376    mov     eax, [ebp + 16*8]     ;; move Int number into RAX 
377    db 48h
378    cmp     eax, 18
379    ja      PrintDefaultString
380PrintExceptionString:
381    shl     eax, 3              ;; multiply by 8 to get offset from StringTable to actual string address
382    add     eax, offset StringTable
383    mov     esi, [eax]
384    jmp     PrintTheString
385PrintDefaultString:
386    mov     esi, offset IntUnknownString
387    ; patch Int number
388    mov     edx, eax
389    call    A2C
390    mov     [esi + 1], al
391    mov     eax, edx
392    shr     eax, 4
393    call    A2C
394    mov     [esi], al
395PrintTheString:        
396    call    PrintString
397    mov     esi, offset String2
398    call    PrintString
399    db 48h
400    mov     eax, [ebp+19*8]    ; CS
401    call    PrintQword
402    mov     al, ':'
403    mov     byte ptr [edi], al
404    add     edi, 2
405    db 48h
406    mov     eax, [ebp+18*8]    ; RIP
407    call    PrintQword
408    mov     esi, offset String3
409    call    PrintString
410    
411    mov     edi, 0b8140h
412    
413    mov     esi, offset StringRax     ; rax
414    call    PrintString
415    db 48h
416    mov     eax, [ebp+15*8]
417    call    PrintQword
418   
419    mov     esi, offset StringRcx     ; rcx
420    call    PrintString
421    db 48h
422    mov     eax, [ebp+14*8]
423    call    PrintQword
424    
425    mov     esi, offset StringRdx     ; rdx
426    call    PrintString
427    db 48h
428    mov     eax, [ebp+13*8]
429    call    PrintQword
430    
431    mov     edi, 0b81e0h
432    
433    mov     esi, offset StringRbx     ; rbx
434    call    PrintString
435    db 48h
436    mov     eax, [ebp+12*8]
437    call    PrintQword
438     
439    mov     esi, offset StringRsp     ; rsp
440    call    PrintString
441    db 48h
442    mov     eax, [ebp+21*8]
443    call    PrintQword
444    
445    mov     esi, offset StringRbp     ; rbp
446    call    PrintString
447    db 48h
448    mov     eax, [ebp+10*8]
449    call    PrintQword
450    
451    mov     edi, 0b8280h
452     
453    mov     esi, offset StringRsi     ; rsi
454    call    PrintString
455    db 48h
456    mov     eax, [ebp+9*8]
457    call    PrintQword
458    
459    mov     esi, offset StringRdi     ; rdi
460    call    PrintString
461    db 48h
462    mov     eax, [ebp+8*8]
463    call    PrintQword
464    
465    mov     esi, offset StringEcode   ; error code
466    call    PrintString
467    db 48h
468    mov     eax, [ebp+17*8]
469    call    PrintQword
470    
471    mov     edi, 0b8320h
472 
473    mov     esi, offset StringR8      ; r8
474    call    PrintString
475    db 48h
476    mov     eax, [ebp+7*8]
477    call    PrintQword
478
479    mov     esi, offset StringR9      ; r9
480    call    PrintString
481    db 48h
482    mov     eax, [ebp+6*8]
483    call    PrintQword
484
485    mov     esi, offset StringR10     ; r10
486    call    PrintString
487    db 48h
488    mov     eax, [ebp+5*8]
489    call    PrintQword
490
491    mov     edi, 0b83c0h
492
493    mov     esi, offset StringR11     ; r11
494    call    PrintString
495    db 48h
496    mov     eax, [ebp+4*8]
497    call    PrintQword
498
499    mov     esi, offset StringR12     ; r12
500    call    PrintString
501    db 48h
502    mov     eax, [ebp+3*8]
503    call    PrintQword
504
505    mov     esi, offset StringR13     ; r13
506    call    PrintString
507    db 48h
508    mov     eax, [ebp+2*8]
509    call    PrintQword
510 
511    mov     edi, 0b8460h
512
513    mov     esi, offset StringR14     ; r14
514    call    PrintString
515    db 48h
516    mov     eax, [ebp+1*8]
517    call    PrintQword
518 
519    mov     esi, offset StringR15     ; r15
520    call    PrintString
521    db 48h
522    mov     eax, [ebp+0*8]
523    call    PrintQword
524
525    mov     esi, offset StringSs      ; ss
526    call    PrintString
527    db 48h
528    mov     eax, [ebp+22*8]
529    call    PrintQword
530  
531    mov     edi, 0b8500h
532
533    mov     esi, offset StringRflags  ; rflags
534    call    PrintString
535    db 48h
536    mov     eax, [ebp+20*8]
537    call    PrintQword
538    
539    mov     edi, 0b8640h
540
541    mov     esi, ebp
542    add     esi, 23*8
543    mov     ecx, 4
544
545    
546OuterLoop:
547    push    ecx
548    mov     ecx, 4
549    db 48h
550    mov     edx, edi
551
552InnerLoop:
553    db 48h
554    mov     eax, [esi]
555    call    PrintQword
556    add     esi, 8
557    mov     al, ' '
558    mov     [edi], al
559    add     edi, 2
560    loop    InnerLoop
561
562    pop     ecx
563    add     edx, 0a0h
564    mov     edi, edx
565    loop    OuterLoop
566
567
568    mov     edi, 0b8960h
569
570    db 48h
571    mov     eax, [ebp+18*8]  ; RIP
572    sub     eax, 8 * 8
573    db 48h
574    mov     esi, eax        ; esi = rip - 8 QWORD linear (total 16 QWORD)
575
576    mov     ecx, 4
577    
578OuterLoop1:
579    push    ecx
580    mov     ecx, 4
581    mov     edx, edi
582
583InnerLoop1:
584    db 48h
585    mov     eax, [esi]
586    call    PrintQword
587    add     esi, 8
588    mov     al, ' '
589    mov     [edi], al
590    add     edi, 2
591    loop    InnerLoop1
592
593    pop     ecx
594    add     edx, 0a0h
595    mov     edi, edx
596    loop    OuterLoop1
597
598
599
600    ;wbinvd
601@@:    
602    jmp     @b
603
604;
605; return
606;
607    mov     esp, ebp
608;    mov     rsp, rbp
609    db 41h
610    db 5fh
611;    pop    r15
612    db 41h
613    db 5eh
614;    pop    r14
615    db 41h
616    db 5dh
617;    pop    r13
618    db 41h
619    db 5ch
620;    pop    r12
621    db 41h
622    db 5bh
623;    pop    r11
624    db 41h
625    db 5ah
626;    pop    r10
627    db 41h
628    db 59h
629;    pop    r9
630    db 41h
631    db 58h
632;    pop    r8
633    pop    edi
634    pop    esi
635    pop    ebp
636    pop    eax ; esp
637    pop    ebx
638    pop    edx
639    pop    ecx
640    pop    eax
641 
642    db 48h
643    db 83h
644    db 0c4h
645    db 10h   
646;    add    esp, 16 ; error code and INT number
647
648    db 48h
649    db 0cfh
650;    iretq
651
652PrintString:
653    push    eax
654@@:
655    mov     al, byte ptr [esi]
656    cmp     al, 0
657    je      @f
658    mov     byte ptr [edi], al
659    db 0ffh
660    db 0c6h
661;    inc     esi
662    add     edi, 2
663    jmp     @b
664@@:
665    pop     eax
666    ret
667        
668;; RAX contains qword to print
669;; RDI contains memory location (screen location) to print it to
670PrintQword:
671    push    ecx
672    push    ebx
673    push    eax
674    
675    db 48h
676    db 0c7h
677    db 0c1h
678    dd 16
679;    mov     rcx, 16
680looptop:
681    db 48h
682    rol     eax, 4
683    mov     bl, al
684    and     bl, 0fh
685    add     bl, '0'
686    cmp     bl, '9'
687    jle     @f
688    add     bl, 7
689@@:
690    mov     byte ptr [edi], bl
691    add     edi, 2
692    loop    looptop
693    ;wbinvd
694    
695    pop     eax
696    pop     ebx
697    pop     ecx
698    ret
699
700ClearScreen:
701    push    eax
702    push    ecx
703    
704    mov     al, ' '
705    mov     ah, 0ch
706    mov     edi, 0b8000h
707    mov     ecx, 80 * 24
708@@:
709    mov     word ptr [edi], ax
710    add     edi, 2
711    loop    @b
712    mov     edi, 0b8000h
713    
714    pop     ecx
715    pop     eax
716
717    ret                
718        
719A2C:
720    and     al, 0fh
721    add     al, '0'
722    cmp     al, '9'
723    jle     @f
724    add     al, 7
725@@:
726    ret
727        
728String1           db  "*** INT ",0
729
730Int0String        db  "00h Divide by 0 -",0
731Int1String        db  "01h Debug exception -",0
732Int2String        db  "02h NMI -",0
733Int3String        db  "03h Breakpoint -",0
734Int4String        db  "04h Overflow -",0
735Int5String        db  "05h Bound -",0
736Int6String        db  "06h Invalid opcode -",0
737Int7String        db  "07h Device not available -",0
738Int8String        db  "08h Double fault -",0
739Int9String        db  "09h Coprocessor seg overrun (reserved) -",0
740Int10String       db  "0Ah Invalid TSS -",0
741Int11String       db  "0Bh Segment not present -",0
742Int12String       db  "0Ch Stack fault -",0
743Int13String       db  "0Dh General protection fault -",0
744Int14String       db  "0Eh Page fault -",0
745Int15String       db  "0Fh (Intel reserved) -",0
746Int16String       db  "10h Floating point error -",0
747Int17String       db  "11h Alignment check -",0
748Int18String       db  "12h Machine check -",0
749Int19String       db  "13h SIMD Floating-Point Exception -",0
750IntUnknownString  db  "??h Unknown interrupt -",0
751
752StringTable       dq  offset Int0String, offset Int1String, offset Int2String, offset Int3String, 
753                      offset Int4String, offset Int5String, offset Int6String, offset Int7String,
754                      offset Int8String, offset Int9String, offset Int10String, offset Int11String,
755                      offset Int12String, offset Int13String, offset Int14String, offset Int15String,
756                      offset Int16String, offset Int17String, offset Int18String, offset Int19String
757
758String2           db  " HALT!! *** (",0
759String3           db  ")",0
760StringRax         db  "RAX=",0
761StringRcx         db  " RCX=",0
762StringRdx         db  " RDX=",0
763StringRbx         db  "RBX=",0
764StringRsp         db  " RSP=",0
765StringRbp         db  " RBP=",0
766StringRsi         db  "RSI=",0
767StringRdi         db  " RDI=",0
768StringEcode       db  " ECODE=",0
769StringR8          db  "R8 =",0
770StringR9          db  " R9 =",0
771StringR10         db  " R10=",0
772StringR11         db  "R11=",0
773StringR12         db  " R12=",0
774StringR13         db  " R13=",0
775StringR14         db  "R14=",0
776StringR15         db  " R15=",0
777StringSs          db  " SS =",0
778StringRflags      db  "RFLAGS=",0
779
780Idtr        df  0
781            df  0
782
783    org 21ffeh
784BlockSignature:
785    dw      0aa55h
786    
787    end
788