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