VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/BIOS/orgs.asm@ 69111

最後變更 在這個檔案從69111是 69025,由 vboxsync 提交於 7 年 前

BIOS: Set INT 41h/46h in ATA setup rather than in assembler startup code.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 64.0 KB
 
1;;
2;; Copyright (C) 2006-2017 Oracle Corporation
3;;
4;; This file is part of VirtualBox Open Source Edition (OSE), as
5;; available from http://www.alldomusa.eu.org. This file is free software;
6;; you can redistribute it and/or modify it under the terms of the GNU
7;; General Public License (GPL) as published by the Free Software
8;; Foundation, in version 2 as it comes in the "COPYING" file of the
9;; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10;; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11;; --------------------------------------------------------------------
12;;
13;; This code is based on:
14;;
15;; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
16;;
17;; Copyright (C) 2002 MandrakeSoft S.A.
18;;
19;; MandrakeSoft S.A.
20;; 43, rue d'Aboukir
21;; 75002 Paris - France
22;; http://www.linux-mandrake.com/
23;; http://www.mandrakesoft.com/
24;;
25;; This library is free software; you can redistribute it and/or
26;; modify it under the terms of the GNU Lesser General Public
27;; License as published by the Free Software Foundation; either
28;; version 2 of the License, or (at your option) any later version.
29;;
30;; This library is distributed in the hope that it will be useful,
31;; but WITHOUT ANY WARRANTY; without even the implied warranty of
32;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33;; Lesser General Public License for more details.
34;;
35;; You should have received a copy of the GNU Lesser General Public
36;; License along with this library; if not, write to the Free Software
37;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38;;
39;;
40
41; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
42; other than GPL or LGPL is available it will apply instead, Oracle elects to use only
43; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
44; a choice of LGPL license versions is made available with the language indicating
45; that LGPLv2 or any later version may be used, or where a choice of which version
46; of the LGPL is applied is otherwise unspecified.
47
48
49include commondefs.inc
50
51EBDA_SEG equ 09FC0h ; starts at 639K
52EBDA_SIZE equ 1 ; 1K
53BASE_MEM_IN_K equ (640 - EBDA_SIZE)
54
55CMOS_ADDR equ 070h
56CMOS_DATA equ 071h
57
58
59PIC_CMD_EOI equ 020h
60PIC_MASTER equ 020h
61PIC_SLAVE equ 0A0h
62
63BIOS_FIX_BASE equ 0E000h
64
65if VBOX_BIOS_CPU ge 80286
66SYS_MODEL_ID equ 0FCh ; PC/AT
67else
68SYS_MODEL_ID equ 0FBh ; PC/XT
69endif
70SYS_SUBMODEL_ID equ 0
71BIOS_REVISION equ 1
72
73BIOS_BUILD_DATE equ '06/23/99'
74BIOS_COPYRIGHT equ 'Oracle VM VirtualBox BIOS'
75
76BX_ROMBIOS32 equ 0
77BX_CALL_INT15_4F equ 1
78
79;; Set a fixed BIOS location, with a marker for verification
80BIOSORG macro addr, addr_minus_two
81.errnz (addr - 2 - addr_minus_two) ;; Couldn't convince wasm to accept $ here. Would've save us a lot of bother and ugly SED.
82 BIOSORG_CHECK_BEFORE addr_minus_two
83 org addr - BIOS_FIX_BASE - 2
84 db 'XM'
85 BIOSORG_CHECK addr
86 endm
87
88;; Set an interrupt vector (not very efficient if multiple vectors are
89;; programmed in one go)
90SET_INT_VECTOR macro vec, segm, offs
91 mov ax, offs
92 mov ds:[vec*4], ax
93 mov ax, segm
94 mov ds:[vec*4+2], ax
95endm
96
97; Set up an environment C code expects. DS must point to the BIOS segment
98; and the direction flag must be cleared(!)
99C_SETUP macro
100 push cs
101 pop ds
102 cld
103endm
104
105
106;; External function in separate modules
107extrn _dummy_isr_function:near
108extrn _log_bios_start:near
109extrn _nmi_handler_msg:near
110extrn _int18_panic_msg:near
111extrn _int09_function:near
112extrn _int13_diskette_function:near
113extrn _int13_eltorito:near
114extrn _int13_cdemu:near
115extrn _int13_cdrom:near
116extrn _cdemu_isactive:near
117extrn _cdemu_emulated_drive:near
118extrn _int13_harddisk:near
119extrn _int13_harddisk_ext:near
120extrn _int14_function:near
121extrn _int15_function:near
122extrn _int15_function_mouse:near
123extrn _int15_function32:near
124extrn _int16_function:near
125extrn _int17_function:near
126extrn _int19_function:near
127extrn _int1a_function:near
128extrn _pci16_function:near
129extrn _int70_function:near
130extrn _int74_function:near
131extrn _apm_function:near
132extrn _ata_init:near
133extrn _scsi_init:near
134extrn _ata_detect:near
135extrn _cdemu_init:near
136extrn _keyboard_init:near
137extrn _print_bios_banner:near
138extrn _inv_op_handler:near
139extrn rom_scan_:near
140ifdef VBOX_WITH_AHCI
141extrn _ahci_init:near
142endif
143if VBOX_BIOS_CPU ge 80286
144extrn _int15_blkmove:near
145endif
146if VBOX_BIOS_CPU ge 80386
147extrn _apic_setup:near
148endif
149
150
151;; Symbols referenced from C code
152public _diskette_param_table
153public _pmode_IDT
154public _rmode_IDT
155public post
156public eoi_both_pics
157public rtc_post
158
159;; Additional publics for easier disassembly and debugging
160ifndef DEBUG
161 DEBUG equ 1
162endif
163ifdef DEBUG
164
165public int08_handler
166public int0e_handler
167public int11_handler
168public int12_handler
169public int13_handler
170public int13_relocated
171if VBOX_BIOS_CPU eq 8086
172public jmp_call_ret_int13_out
173endif
174public int15_handler
175public int17_handler
176public int19_handler
177public int19_relocated
178public dummy_iret
179public nmi
180public rom_fdpt
181public cpu_reset
182public normal_post
183public eoi_jmp_post
184public no_eoi_jmp_post
185public eoi_master_pic
186public ebda_post
187public seg_40_value
188public hard_drive_post
189public int13_legacy
190public int70_handler
191public int75_handler
192public int15_handler32
193public int15_handler_mouse
194public iret_modify_cf
195public init_pic
196public floppy_post
197public int13_out
198public int13_disk
199public int13_notfloppy
200public int13_legacy
201public int13_noeltorito
202public int1c_handler
203public int10_handler
204public int74_handler
205public int76_handler
206public detect_parport
207public detect_serial
208public font8x8
209
210endif
211
212;; NOTE: The last 8K of the ROM BIOS are peppered with fixed locations which
213;; must be retained for compatibility. As a consequence, some of the space is
214;; going to be wasted, but the gaps should be filled with miscellaneous code
215;; and data when possible.
216
217SET_DEFAULT_CPU_286
218
219BIOSSEG segment 'CODE'
220 assume cs:BIOSSEG
221
222;;
223;; Start of fixed code - eoi_jmp_post is kept near here to allow short jumps.
224;;
225 BIOSORG 0E030h, 0E02Eh
226eoi_both_pics:
227 mov al, PIC_CMD_EOI
228 out PIC_SLAVE, al
229eoi_master_pic:
230 mov al, PIC_CMD_EOI
231 out PIC_MASTER, al
232 ret
233
234 ;; routine to write the pointer in DX:AX to memory starting
235 ;; at DS:BX (repeat CX times)
236 ;; - modifies BX, CX
237set_int_vects proc near
238
239 mov [bx], ax
240 mov [bx+2], dx
241 add bx, 4
242 loop set_int_vects
243 ret
244
245set_int_vects endp
246
247eoi_jmp_post:
248 call eoi_both_pics
249no_eoi_jmp_post:
250 xor ax, ax
251 mov ds, ax
252 jmp dword ptr ds:[0467h]
253
254seg_40_value: dw 40h ;; Replaces a push 40; pop ds.
255
256;; --------------------------------------------------------
257;; POST entry point
258;; --------------------------------------------------------
259 BIOSORG 0E05Bh, 0E059h
260post:
261 cli
262
263if VBOX_BIOS_CPU ge 80286
264 ;; Check if in protected (V86) mode. If so, the CPU needs
265 ;; to be reset.
266 .286p
267 smsw ax
268 test ax, 1
269 jz in_real_mode
270 SET_DEFAULT_CPU_286
271else
272 jmp in_real_mode
273endif
274
275 ;; Reset processor to get out of protected mode. Use system
276 ;; port instead of KBC.
277reset_sys:
278 mov al, 1
279 out 92h, al
280 jmp $ ; not strictly necessary in a VM
281
282
283in_real_mode:
284 ;; read the CMOS shutdown status
285 mov al, 0Fh
286 out CMOS_ADDR, al
287 in al, CMOS_DATA
288
289 ;; save status
290 xchg ah, al
291
292 ;; Check KBC self-test/shutdown flag. If it is set, we need
293 ;; to check for a reboot attempt.
294 in al, 64h
295 test al, 4 ; clear flag indicates cold boot
296 jz cont_post
297
298 ;; Warm boot, check the shutdown byte.
299 mov al, ah
300 or al, al
301 jnz cont_post
302
303 ;; Warm boot but shutdown byte is zero. This is either a warm
304 ;; boot request or an attempt to reset the system via triple
305 ;; faulting the CPU or similar. Check reboot flag.
306 ;; NB: At this point, registers need not be preserved.
307 mov ds, cs:[seg_40_value]
308 cmp word ptr ds:[72h], 1234h
309 jnz reset_sys ; trigger system reset
310
311cont_post:
312 ;; reset the shutdown status in CMOS
313 mov al, 0Fh
314 out CMOS_ADDR, al
315 mov al, 0
316 out CMOS_DATA, al
317
318 ;; pre-check the shutdown status - shutdown codes 9/A leave
319 ;; the hardware alone
320 mov al, ah
321 cmp al, 09h
322 jz check_shutdown
323 cmp al, 0Ah
324 jz check_shutdown
325
326 xor al, al
327
328 ;; reset the DMA controllers
329 out 00Dh, al
330 out 0DAh, al
331
332 ;; then initialize the DMA controllers
333 mov al, 0C0h
334 out 0D6h, al ; enable channel 4 cascade
335 mov al, 0
336 out 0D4h, al ; unmask channel 4
337
338check_shutdown:
339 ;; examine the shutdown status code
340 mov al, ah
341 cmp al, 0
342 jz normal_post
343
344 cmp al, 0Dh
345 jae normal_post
346 cmp al, 9
347 jne check_next_std
348 jmp return_blkmove
349check_next_std:
350
351 ;; 05h = EOI + jump through 40:67
352 cmp al, 5
353 je eoi_jmp_post
354 ;; 0ah = jump through 40:67 (no EOI) ;ba x 1 %fe05b ; ba x 1 %18b81
355 cmp al, 0ah
356 je no_eoi_jmp_post
357
358 ;; any other shutdown status values are ignored
359 ;; OpenSolaris sets the status to 0Ah in some cases?
360 jmp normal_post
361
362normal_post:
363 ;; shutdown code 0: normal startup
364
365 ;; Set up the stack top at 0:7800h. The stack should not be
366 ;; located above 0:7C00h; that conflicts with PXE, which
367 ;; considers anything above that address to be fair game.
368 ;; The traditional locations are 30:100 (PC) or 0:400 (PC/AT).
369 mov ax, 7800h
370 mov sp, ax
371 xor ax, ax
372 mov ds, ax
373 mov ss, ax
374
375 ;; clear the bottom of memory except for the word at 40:72
376 ;; TODO: Why not clear all of it? What's the point?
377 mov es, ax
378 xor di, di
379 cld
380 mov cx, 0472h / 2
381 rep stosw
382 inc di
383 inc di
384 mov cx, (1000h - 0472h - 2) / 2
385 rep stosw
386
387 ;; clear the remaining base memory except for the top
388 ;; of the EBDA (the MP table is planted there)
389 xor bx, bx
390memory_zero_loop:
391 add bx, 1000h
392 cmp bx, 9000h
393 jae memory_cleared
394 mov es, bx
395 xor di, di
396 mov cx, 8000h ; 32K words
397 rep stosw
398 jmp memory_zero_loop
399memory_cleared:
400 mov es, bx
401 xor di, di
402 mov cx, 7FF8h ; all but the last 16 bytes
403 rep stosw
404 xor bx, bx
405
406
407 C_SETUP
408 call _log_bios_start
409
410if VBOX_BIOS_CPU ge 80386
411 call pmode_setup
412endif
413
414 ;; set all interrupts in 00h-5Fh range to default handler
415 xor bx, bx
416 mov ds, bx
417 mov cx, 60h ; leave the rest as zeros
418 mov ax, dummy_iret
419 mov dx, BIOSSEG
420 call set_int_vects
421
422 ;; also set 68h-77h to default handler; note that the
423 ;; 60h-67h range must contain zeros for certain programs
424 ;; to function correctly
425 mov bx, 68h * 4
426 mov cx, 10h
427 call set_int_vects
428
429 ;; base memory in K to 40:13
430 mov ax, BASE_MEM_IN_K
431 mov ds:[413h], ax
432
433 ;; manufacturing test at 40:12
434 ;; zeroed out above
435
436 ;; set up various service vectors
437 ;; TODO: This should use the table at FEF3h instead
438 SET_INT_VECTOR 06h, BIOSSEG, int06_handler
439 SET_INT_VECTOR 11h, BIOSSEG, int11_handler
440 SET_INT_VECTOR 12h, BIOSSEG, int12_handler
441 SET_INT_VECTOR 15h, BIOSSEG, int15_handler
442 SET_INT_VECTOR 17h, BIOSSEG, int17_handler
443 SET_INT_VECTOR 18h, BIOSSEG, int18_handler
444 SET_INT_VECTOR 19h, BIOSSEG, int19_handler
445 SET_INT_VECTOR 1Ch, BIOSSEG, int1c_handler
446
447 call ebda_post
448
449 ;; Initialize PCI devices. This can and should be done early.
450if VBOX_BIOS_CPU ge 80386 ; (Impossible to do on 16-bit CPUs.)
451 call pcibios_init_iomem_bases
452 call pcibios_init_irqs
453endif
454 SET_INT_VECTOR 1Ah, BIOSSEG, int1a_handler
455
456 ;; PIT setup
457 SET_INT_VECTOR 08h, BIOSSEG, int08_handler
458 mov al, 34h ; timer 0, binary, 16-bit, mode 2
459 out 43h, al
460 mov al, 0 ; max count -> ~18.2 Hz
461 out 40h, al
462 out 40h, al
463
464 ;; video setup - must be done before POSTing VGA ROM
465 SET_INT_VECTOR 10h, BIOSSEG, int10_handler
466
467 ;; keyboard setup
468 SET_INT_VECTOR 09h, BIOSSEG, int09_handler
469 SET_INT_VECTOR 16h, BIOSSEG, int16_handler
470
471 xor ax, ax
472 mov ds, ax
473 ;; TODO: What's the point? The BDA is zeroed already?!
474 mov ds:[417h], al ; keyboard shift flags, set 1
475 mov ds:[418h], al ; keyboard shift flags, set 2
476 mov ds:[419h], al ; keyboard Alt-numpad work area
477 mov ds:[471h], al ; keyboard Ctrl-Break flag
478 mov ds:[497h], al ; keyboard status flags 4
479 mov al, 10h
480 mov ds:[496h], al ; keyboard status flags 3
481
482 mov bx, 1Eh
483 mov ds:[41Ah], bx ; keyboard buffer head
484 mov ds:[41Ch], bx ; keyboard buffer tail
485 mov ds:[480h], bx ; keyboard buffer start
486 mov bx, 3Eh
487 mov ds:[482h], bx ; keyboard buffer end
488
489 ;; store CMOS equipment byte in BDA
490 mov al, 14h
491 out CMOS_ADDR, al
492 in al, CMOS_DATA
493 mov ds:[410h], al
494
495 push ds
496 C_SETUP
497
498 ;; Scan for video ROMs in the C000-C800 range. This is done
499 ;; early so that errors are displayed on the screen.
500 mov ax, 0C000h
501 mov dx, 0C800h
502 call rom_scan_
503
504 ;; Initialize the keyboard
505 call _keyboard_init
506 pop ds
507
508 ;; parallel setup
509 SET_INT_VECTOR 0Fh, BIOSSEG, dummy_iret
510 xor ax, ax
511 mov ds, ax
512 xor bx, bx
513 mov cl, 14h ; timeout value
514 mov dx, 378h ; parallel port 1
515 call detect_parport
516 mov dx, 278h ; parallel port 2
517 call detect_parport
518 DO_shl bx, 0Eh
519 mov ax, ds:[410h] ; equipment word
520 and ax, 3FFFh
521 or ax, bx ; set number of parallel ports
522 mov ds:[410h], ax ; store in BDA
523
524 ;; Serial setup
525 SET_INT_VECTOR 0Bh, BIOSSEG, dummy_isr ; IRQ 3
526 SET_INT_VECTOR 0Ch, BIOSSEG, dummy_isr ; IRQ 4
527 SET_INT_VECTOR 14h, BIOSSEG, int14_handler
528 xor bx, bx
529 mov cl, 0Ah ; timeout value
530 mov dx, 3F8h ; first serial address
531 call detect_serial
532 mov dx, 2F8h ; second serial address
533 call detect_serial
534 mov dx, 3E8h ; third serial address
535 call detect_serial
536 mov dx, 2E8h ; fourth serial address
537 call detect_serial
538 DO_shl bx, 9
539 mov ax, ds:[410h] ; equipment word
540 and ax, 0F1FFh ; bits 9-11 determine serial ports
541 or ax, bx
542 mov ds:[410h], ax
543
544 ;; CMOS RTC
545 SET_INT_VECTOR 4Ah, BIOSSEG, dummy_iret ; TODO: redundant?
546 SET_INT_VECTOR 70h, BIOSSEG, int70_handler
547 ;; BIOS DATA AREA 4CEh ???
548 call rtc_post
549
550 jmp norm_post_cont
551
552
553;; --------------------------------------------------------
554;; NMI handler
555;; --------------------------------------------------------
556 BIOSORG 0E2C3h, 0E2C1h
557nmi:
558 C_SETUP
559 call _nmi_handler_msg
560 iret
561
562int75_handler:
563 out 0F0h, al ; clear IRQ13
564 call eoi_both_pics
565 int 2 ; emulate legacy NMI
566 iret
567
568
569hard_drive_post proc near
570
571 xor ax, ax
572 mov ds, ax
573 ;; TODO: Didn't we just clear the entire EBDA?
574 mov ds:[474h], al ; last HD operation status
575 mov ds:[477h], al ; HD port offset (XT only???)
576 mov ds:[48Ch], al ; HD status register
577 mov ds:[48Dh], al ; HD error register
578 mov ds:[48Eh], al ; HD task complete flag
579 mov al, 0C0h
580 mov ds:[476h], al ; HD control byte
581 ;; set up hard disk interrupt vectors
582 SET_INT_VECTOR 13h, BIOSSEG, int13_handler
583 SET_INT_VECTOR 76h, BIOSSEG, int76_handler
584 ;; The ATA init code sets up INT 41h/46h FDPT pointers
585 ret
586
587hard_drive_post endp
588
589
590norm_post_cont:
591 ;; PS/2 mouse setup
592 SET_INT_VECTOR 74h, BIOSSEG, int74_handler
593
594 ;; IRQ 13h (FPU exception) setup
595 SET_INT_VECTOR 75h, BIOSSEG, int75_handler
596
597 call init_pic
598
599 C_SETUP
600
601if VBOX_BIOS_CPU ge 80386
602 ;; Set up local APIC
603 .386
604 pushad
605 call _apic_setup
606 popad
607 SET_DEFAULT_CPU_286
608endif
609
610 ;; ATA/ATAPI driver setup
611 call _ata_init
612 call _ata_detect
613
614ifdef VBOX_WITH_AHCI
615 ; AHCI driver setup
616 ;; TODO: AHCI initialization needs timer, but enabling
617 ;; interrupts elsewhere may be risky. Just do it around
618 ;; the AHCI init.
619 sti
620 call _ahci_init
621 cli
622endif
623
624ifdef VBOX_WITH_SCSI
625 ; SCSI driver setup
626 call _scsi_init
627endif
628
629 ;; floppy setup
630 call floppy_post
631
632 ;; hard drive setup
633 call hard_drive_post
634
635 C_SETUP ; in case assembly code changed things
636 ;; Scan for additional ROMs in the C800-EFFF range
637 mov ax, 0C800h
638 mov dx, 0F000h
639 call rom_scan_
640
641if VBOX_BIOS_CPU ge 80386
642 ;; The POST code does not bother preserving high bits of the
643 ;; 32-bit registers. Now is a good time to clear them so that
644 ;; there's no garbage left in high bits.
645 .386
646 xor eax, eax
647 xor ebx, ebx
648 xor ecx, ecx
649 xor edx, edx
650 .286
651endif
652
653 call _print_bios_banner
654
655 ;; El Torito floppy/hard disk emulation
656 call _cdemu_init
657
658 ; TODO: what's the point of enabling interrupts here??
659 sti ; enable interrupts
660 int 19h
661 ;; does not return here
662 sti
663wait_forever:
664 hlt
665 jmp wait_forever
666 cli
667 hlt
668
669
670;;
671;; Return from block move (shutdown code 09h). Care must be taken to disturb
672;; register and memory state as little as possible.
673;;
674return_blkmove:
675 .286p
676 mov ax, 40h
677 mov ds, ax
678 ;; restore user stack
679 mov ss, ds:[69h]
680 mov sp, ds:[67h]
681 ;; reset A20 gate
682 in al, 92h
683 and al, 0FDh
684 out 92h, al
685 ;; ensure proper real mode IDT
686 lidt fword ptr cs:_rmode_IDT
687 ;; restore user segments
688 pop ds
689 pop es
690 ;; set up BP
691 mov bp, sp
692 ;; restore status code
693 in al, 80h
694 mov [bp+15], al
695 ;; set ZF/CF
696 cmp ah,al ; AH is zero here!
697 ;; restore registers and return
698 popa
699 sti
700 retf 2
701 SET_DEFAULT_CPU_286
702
703
704;; --------------------------------------------------------
705;; INT 13h handler - Disk services
706;; --------------------------------------------------------
707 BIOSORG 0E3FEh, 0E3FCh
708
709int13_handler:
710 jmp int13_relocated
711
712
713;; --------------------------------------------------------
714;; Fixed Disk Parameter Table
715;; --------------------------------------------------------
716 BIOSORG_CHECK 0E401h ; fixed wrt preceding
717
718rom_fdpt:
719
720;; --------------------------------------------------------
721;; INT 19h handler - Boot load service
722;; --------------------------------------------------------
723 BIOSORG 0E6F2h, 0E6F0h
724
725int19_handler:
726 jmp int19_relocated
727
728
729
730;; --------------------------------------------------------
731;; System BIOS Configuration Table
732;; --------------------------------------------------------
733 BIOSORG_CHECK 0E6F5h ; fixed wrt preceding
734; must match BIOS_CONFIG_TABLE
735bios_cfg_table:
736 dw 9 ; table size in bytes
737 db SYS_MODEL_ID
738 db SYS_SUBMODEL_ID
739 db BIOS_REVISION
740 ; Feature byte 1
741 ; b7: 1=DMA channel 3 used by hard disk
742 ; b6: 1=2 interrupt controllers present
743 ; b5: 1=RTC present
744 ; b4: 1=BIOS calls int 15h/4Fh for every key
745 ; b3: 1=wait for extern event supported (Int 15h/41h)
746 ; b2: 1=extended BIOS data area used
747 ; b1: 0=AT or ESDI bus, 1=MicroChannel
748 ; b0: 1=Dual bus (MicroChannel + ISA)
749ifdef BX_CALL_INT15_4F
750 db 74h; or USE_EBDA
751else
752 db 64h; or USE_EBDA
753endif
754 ; Feature byte 2
755 ; b7: 1=32-bit DMA supported
756 ; b6: 1=int16h, function 9 supported
757 ; b5: 1=int15h/C6h (get POS data) supported
758 ; b4: 1=int15h/C7h (get mem map info) supported
759 ; b3: 1=int15h/C8h (en/dis CPU) supported
760 ; b2: 1=non-8042 kb controller
761 ; b1: 1=data streaming supported
762 ; b0: reserved
763 db 40h
764 ; Feature byte 3
765 ; b7: not used
766 ; b6: reserved
767 ; b5: reserved
768 ; b4: POST supports ROM-to-RAM enable/disable
769 ; b3: SCSI on system board
770 ; b2: info panel installed
771 ; b1: Initial Machine Load (IML) system - BIOS on disk
772 ; b0: SCSI supported in IML
773 db 0
774 ; Feature byte 4
775 ; b7: IBM private
776 ; b6: EEPROM present
777 ; b5-3: ABIOS presence (011 = not supported)
778 ; b2: private
779 ; b1: memory split above 16Mb supported
780 ; b0: POSTEXT directly supported by POST
781 db 0
782 ; Feature byte 5 (IBM)
783 ; b1: enhanced mouse
784 ; b0: flash EPROM
785 db 0
786
787
788;; --------------------------------------------------------
789;; Baud Rate Generator Table
790;; --------------------------------------------------------
791 BIOSORG 0E729h, 0E727h
792
793
794;; --------------------------------------------------------
795;; INT 14h handler - Serial Communication Service
796;; --------------------------------------------------------
797 BIOSORG 0E739h, 0E737h
798int14_handler:
799 push ds
800 push es
801 DO_pusha
802 C_SETUP
803 call _int14_function
804 DO_popa
805 pop es
806 pop ds
807 iret
808
809
810
811;;
812;; Handler for unexpected hardware interrupts
813;;
814dummy_isr:
815 push ds
816 push es
817 DO_pusha
818 C_SETUP
819 call _dummy_isr_function
820 DO_popa
821 pop es
822 pop ds
823 iret
824
825
826init_pic proc near
827
828 mov al, 11h ; send init commands
829 out PIC_MASTER, al
830 out PIC_SLAVE, al
831 mov al, 08h ; base 08h
832 out PIC_MASTER+1, al
833 mov al, 70h ; base 70h
834 out PIC_SLAVE+1, al
835 mov al, 04h ; master PIC
836 out PIC_MASTER+1, al
837 mov al, 02h ; slave PIC
838 out PIC_SLAVE+1, al
839 mov al, 01h
840 out PIC_MASTER+1, al
841 out PIC_SLAVE+1, al
842 mov al, 0B8h ; unmask IRQs 0/1/2/6
843 out PIC_MASTER+1, al
844 mov al, 08Fh
845 out PIC_SLAVE+1, al ; unmask IRQs 12/13/14
846 ret
847
848init_pic endp
849
850ebda_post proc near
851
852 SET_INT_VECTOR 0Dh, BIOSSEG, dummy_isr ; IRQ 5
853 SET_INT_VECTOR 0Fh, BIOSSEG, dummy_isr ; IRQ 7
854 SET_INT_VECTOR 72h, BIOSSEG, dummy_isr ; IRQ 10
855 SET_INT_VECTOR 73h, BIOSSEG, dummy_isr ; IRQ 11
856 SET_INT_VECTOR 77h, BIOSSEG, dummy_isr ; IRQ 15
857
858 mov ax, EBDA_SEG
859 mov ds, ax
860 mov byte ptr ds:[0], EBDA_SIZE
861 ;; store EBDA seg in 40:0E
862 xor ax, ax
863 mov ds, ax
864 mov word ptr ds:[40Eh], EBDA_SEG
865 ret
866
867ebda_post endp
868
869
870
871;; --------------------------------------------------------
872;; INT 16h handler - Keyboard service
873;; --------------------------------------------------------
874 BIOSORG 0E82Eh, 0E82Ch
875int16_handler:
876 sti
877 ;; Flags are saved *after* enabling interrupts, and with
878 ;; implicitly cleared TF. Software may depend on that.
879 pushf
880 push es
881 push ds
882 DO_pusha
883
884 cmp ah, 0
885 je int16_F00
886
887 cmp ah, 10h
888 je int16_F00
889
890 C_SETUP
891 call _int16_function
892 DO_popa
893 pop ds
894 pop es
895 add sp, 2 ; Skip saved flags
896 iret
897
898int16_F00:
899 mov bx, 40h ; TODO: why 40h here and 0 elsewhere?
900 mov ds, bx
901int16_wait_for_key:
902 cli
903 mov bx, ds:[1Ah]
904 cmp bx, ds:[1Ch]
905 jne int16_key_found
906 sti
907 nop
908; TODO: review/enable?
909if 0
910 push ax
911 mov ax, 9002h
912 int 15h
913 pop ax
914endif
915 jmp int16_wait_for_key
916
917int16_key_found:
918 C_SETUP
919 call _int16_function
920 DO_popa
921 pop ds
922 pop es
923 add sp, 2 ; Skip saved flags
924; TODO: review/enable? If so, flags should be restored here?
925if 0
926 push ax
927 mov ax, 9202h
928 int 15h
929 pop ax
930endif
931 iret
932
933
934if VBOX_BIOS_CPU ge 80386
935;; Quick and dirty protected mode entry/exit routines
936include pmode.inc
937
938;; Initialization code which needs to run in protected mode (LAPIC etc.)
939include pmsetup.inc
940endif
941
942
943KBDC_DISABLE EQU 0ADh
944KBDC_ENABLE EQU 0AEh
945KBC_CMD EQU 64h
946KBC_DATA EQU 60h
947
948;; --------------------------------------------------------
949;; INT 09h handler - Keyboard ISR (IRQ 1)
950;; --------------------------------------------------------
951 BIOSORG 0E987h, 0E985h
952int09_handler:
953 cli ; TODO: why? they're off already!
954 push ax
955 mov al, KBDC_DISABLE
956 out KBC_CMD, al
957
958 in al, KBC_DATA
959 push ds
960 DO_pusha
961 cld ; Before INT 15h (and any C code)
962ifdef BX_CALL_INT15_4F
963 mov ah, 4Fh
964 stc
965 int 15h ; keyboard intercept
966 jnc int09_done
967endif
968 sti ; Only after calling INT 15h
969
970 ;; check for extended key
971 cmp al, 0E0h
972 jne int09_check_pause
973 xor ax, ax
974 mov ds, ax
975 or byte ptr ds:[496h], 2 ; mf2_state |= 0x02
976 jmp int09_done
977
978int09_check_pause:
979 cmp al, 0E1h ; pause key?
980 jne int09_process_key
981 xor ax, ax
982 mov ds, ax
983 or byte ptr ds:[496h], 1 ; mf2_state | 0x01
984 jmp int09_done
985
986int09_process_key:
987 push es
988 C_SETUP
989 call _int09_function
990 pop es
991
992int09_done:
993 DO_popa
994 pop ds
995 cli
996 call eoi_master_pic
997
998 mov al, KBDC_ENABLE
999 out KBC_CMD, al
1000 pop ax
1001 iret
1002
1003
1004;; --------------------------------------------------------
1005;; INT 06h handler - Invalid Opcode Exception
1006;; --------------------------------------------------------
1007
1008int06_handler:
1009 DO_pusha
1010 push es
1011 push ds
1012 C_SETUP
1013 call _inv_op_handler
1014 pop ds
1015 pop es
1016 DO_popa
1017 iret
1018
1019;; --------------------------------------------------------
1020;; INT 13h handler - Diskette service
1021;; --------------------------------------------------------
1022 BIOSORG 0EC59h, 0EC57h
1023int13_diskette:
1024 jmp int13_noeltorito
1025
1026
1027
1028;; --------------------------------------------------------
1029;; INT 13h handler - Disk service
1030;; --------------------------------------------------------
1031int13_relocated:
1032 ;; check for an El-Torito function
1033 cmp ah, 4Ah
1034 jb int13_not_eltorito
1035
1036 cmp ah, 4Dh
1037 ja int13_not_eltorito
1038
1039 DO_pusha
1040 push es
1041 push ds
1042 C_SETUP ; TODO: setup C envrionment only once?
1043 DO_JMP_CALL_EX _int13_eltorito, int13_out, jmp_call_ret_int13_out ; ELDX not used
1044if VBOX_BIOS_CPU eq 8086
1045jmp_call_ret_int13_out: dw offset int13_out
1046endif
1047
1048int13_not_eltorito:
1049 push es
1050 push ax ; TODO: better register save/restore
1051 push bx
1052 push cx
1053 push dx
1054
1055 ;; check if emulation is active
1056 call _cdemu_isactive
1057 cmp al, 0
1058 je int13_cdemu_inactive
1059
1060 ;; check if access to the emulated drive
1061 call _cdemu_emulated_drive
1062 pop dx ; recover dx (destroyed by C code)
1063 push dx
1064 cmp al, dl ; INT 13h on emulated drive
1065 jne int13_nocdemu
1066
1067 pop dx
1068 pop cx
1069 pop bx
1070 pop ax
1071 pop es
1072
1073 DO_pusha
1074 push es
1075 push ds
1076 C_SETUP ; TODO: setup environment only once?
1077
1078 DO_JMP_CALL_EX _int13_cdemu, int13_out, jmp_call_ret_int13_out ; ELDX not used
1079
1080int13_nocdemu:
1081 and dl, 0E0h ; mask to get device class
1082 cmp al, dl
1083 jne int13_cdemu_inactive
1084
1085 pop dx
1086 pop cx
1087 pop bx
1088 pop ax
1089 pop es
1090
1091 push ax
1092 push cx
1093 push dx
1094 push bx
1095
1096 dec dl ; real drive is dl - 1
1097 jmp int13_legacy
1098
1099int13_cdemu_inactive:
1100 pop dx
1101 pop cx
1102 pop bx
1103 pop ax
1104 pop es
1105
1106int13_noeltorito:
1107 push ax
1108 push cx
1109 push dx
1110 push bx
1111int13_legacy:
1112 push dx ; push eltorito dx in place of sp
1113 push bp
1114 push si
1115 push di
1116 push es
1117 push ds
1118 C_SETUP ; TODO: setup environment only once?
1119
1120 ;; now the registers can be restored with
1121 ;; pop ds; pop es; DO_popa; iret
1122 test dl, 80h ; non-removable?
1123 jnz int13_notfloppy
1124
1125 DO_JMP_CALL_EX _int13_diskette_function, int13_out, jmp_call_ret_int13_out
1126
1127int13_notfloppy:
1128 cmp dl, 0E0h
1129 jb int13_notcdrom
1130
1131 ;; ebx may be modified, save here
1132 ;; TODO: check/review 32-bit register use
1133 ;; @todo figure if 80286/8086 variant is applicable.
1134 .386
1135 shr ebx, 16
1136 push bx
1137 call _int13_cdrom
1138 pop bx
1139 shl ebx, 16
1140 SET_DEFAULT_CPU_286
1141 jmp int13_out
1142
1143int13_notcdrom:
1144int13_disk:
1145 cmp ah,40h
1146 ja int13x
1147 call _int13_harddisk
1148 jmp int13_out
1149
1150int13x:
1151 call _int13_harddisk_ext
1152
1153int13_out:
1154 pop ds
1155 pop es
1156 DO_popa
1157 iret
1158
1159
1160
1161; parallel port detection: port in dx, index in bx, timeout in cl
1162detect_parport proc near
1163
1164 push dx
1165 inc dx
1166 inc dx
1167 in al, dx
1168 and al, 0DFh ; clear input mode
1169 out dx, al
1170 pop dx
1171 mov al, 0AAh
1172 out dx, al
1173 in al, dx
1174 cmp al, 0AAh
1175 jne no_parport
1176
1177 push bx
1178 shl bx, 1
1179 mov [bx+408h], dx ; parallel I/O address
1180 pop bx
1181 mov [bx+478h], cl ; parallel printer timeout
1182 inc bx
1183no_parport:
1184 ret
1185
1186detect_parport endp
1187
1188; setial port detection: port in dx, index in bx, timeout in cl
1189detect_serial proc near
1190
1191 push dx
1192 inc dx
1193 mov al, 2
1194 out dx, al
1195 in al, dx
1196 cmp al, 2
1197 jne no_serial
1198
1199 inc dx
1200 in al, dx
1201 cmp al, 2
1202 jne no_serial
1203
1204 dec dx
1205 xor al, al
1206 pop dx
1207 push bx
1208 shl bx, 1
1209 mov [bx+400h], dx ; serial I/O address
1210 pop bx
1211 mov [bx+47Ch], cl ; serial timeout
1212 inc bx
1213 ret
1214
1215no_serial:
1216 pop dx
1217 ret
1218
1219detect_serial endp
1220
1221
1222;;
1223;; POST: Floppy drive
1224;;
1225floppy_post proc near
1226
1227 xor ax, ax
1228 mov ds, ax
1229
1230 ;; TODO: This code is really stupid. Zeroing the BDA byte
1231 ;; by byte is dumb, and it's been already zeroed elsewhere!
1232 mov al, 0
1233 mov ds:[43Eh], al ; drive 0/1 uncalibrated, no IRQ
1234 mov ds:[43Fh], al ; motor status
1235 mov ds:[440h], al ; motor timeout counter
1236 mov ds:[441h], al ; controller status return code
1237 mov ds:[442h], al ; hd/floppy ctlr status register
1238 mov ds:[443h], al ; controller status register 1
1239 mov ds:[444h], al ; controller status register 2
1240 mov ds:[445h], al ; cylinder number
1241 mov ds:[446h], al ; head number
1242 mov ds:[447h], al ; sector number
1243 mov ds:[448h], al ; bytes written
1244
1245 mov ds:[48Bh], al ; configuration data
1246
1247 mov al, 10h ; floppy drive type
1248 out CMOS_ADDR, al
1249 in al, CMOS_DATA
1250 mov ah, al ; save drive type byte
1251
1252look_drive0:
1253 ; TODO: pre-init bl to reduce jumps
1254 DO_shr al, 4 ; drive 0 in high nibble
1255 jz f0_missing ; jump if no drive
1256 mov bl, 7 ; drv0 determined, multi-rate, chgline
1257 jmp look_drive1
1258
1259f0_missing:
1260 mov bl, 0 ; no drive 0
1261
1262look_drive1:
1263 mov al, ah ; restore CMOS data
1264 and al, 0Fh ; drive 1 in low nibble
1265 jz f1_missing
1266 or bl, 70h ; drv1 determined, multi-rate, chgline
1267f1_missing:
1268 mov ds:[48Fh], bl ; store in BDA
1269
1270 ;; TODO: See above. Dumb *and* redundant!
1271 mov al, 0
1272 mov ds:[490h], al ; drv0 media state
1273 mov ds:[491h], al ; drv1 media state
1274 mov ds:[492h], al ; drv0 operational state
1275 mov ds:[493h], al ; drv1 operational state
1276 mov ds:[494h], al ; drv0 current cylinder
1277 mov ds:[495h], al ; drv1 current cylinder
1278
1279 mov al, 2
1280 out 0Ah, al ; unmask DMA channel 2
1281
1282 SET_INT_VECTOR 1Eh, BIOSSEG, _diskette_param_table
1283 SET_INT_VECTOR 40h, BIOSSEG, int13_diskette
1284 SET_INT_VECTOR 0Eh, BIOSSEG, int0e_handler ; IRQ 6
1285
1286 ret
1287
1288floppy_post endp
1289
1290
1291bcd_to_bin proc near
1292
1293 ;; in : AL in packed BCD format
1294 ;; out: AL in binary, AH always 0
1295if VBOX_BIOS_CPU ge 80186
1296 shl ax, 4
1297 shr al, 4
1298else
1299 push cx
1300 mov cl, 4
1301 shl ax, cl
1302 shr al, cl
1303 pop cx
1304endif
1305 aad
1306 ret
1307
1308bcd_to_bin endp
1309
1310rtc_post proc near
1311
1312if VBOX_BIOS_CPU lt 80386 ;; @todo fix loopy code below
1313 ;; get RTC seconds
1314 mov al, 0
1315 out CMOS_ADDR, al
1316 in al, CMOS_DATA ; RTC seconds, in BCD
1317 call bcd_to_bin ; ax now has seconds in binary
1318 test al, al
1319 xor ah, ah
1320 mov dx, 0x1234 ; 18206507*0x100/1000000 = 0x1234 (4660.865792)
1321 mul dx
1322 mov cx, ax ; tick count in dx:cx
1323
1324 ;; get RTC minutes
1325 mov al, 2
1326 out CMOS_ADDR, al
1327 in al, CMOS_DATA ; RTC minutes, in BCD
1328 call bcd_to_bin ; eax now has minutes in binary
1329 test al, al
1330 jz rtc_post_hours
1331rtc_pos_min_loop: ; 18206507*60*0x100/1000000 = 0x44463 (279651.94752)
1332 add cx, 0x4463
1333 adc dx, 0x0004
1334 dec al
1335 jnz rtc_pos_min_loop
1336
1337 ;; get RTC hours
1338rtc_post_hours:
1339 mov al, 4
1340 out CMOS_ADDR, al
1341 in al, CMOS_DATA ; RTC hours, in BCD
1342 call bcd_to_bin ; eax now has hours in binary
1343 test al, al
1344 jz rtc_pos_shift
1345rtc_pos_hour_loop: ; 18206507*3600*0x100/1000000 = 0x100076C (16779116.8512)
1346 add cx, 0x076C
1347 adc dx, 0x0100
1348 dec al
1349 jnz rtc_pos_hour_loop
1350
1351rtc_pos_shift:
1352 mov cl, ch
1353 mov ch, dl
1354 mov dl, dh
1355 xor dh, dh
1356 mov ds:[46Ch], cx ; timer tick count
1357 mov ds:[46Ch+2], dx ; timer tick count
1358 mov ds:[470h], dh ; rollover flag
1359
1360else
1361 .386
1362 ;; get RTC seconds
1363 xor eax, eax
1364 mov al, 0
1365 out CMOS_ADDR, al
1366 in al, CMOS_DATA ; RTC seconds, in BCD
1367 call bcd_to_bin ; eax now has seconds in binary
1368 mov edx, 18206507
1369 mul edx
1370 mov ebx, 1000000
1371 xor edx, edx
1372 div ebx
1373 mov ecx, eax ; total ticks in ecx
1374
1375 ;; get RTC minutes
1376 xor eax, eax
1377 mov al, 2
1378 out CMOS_ADDR, al
1379 in al, CMOS_DATA ; RTC minutes, in BCD
1380 call bcd_to_bin ; eax now has minutes in binary
1381 mov edx, 10923904
1382 mul edx
1383 mov ebx, 10000
1384 xor edx, edx
1385 div ebx
1386 add ecx, eax ; add to total ticks
1387
1388 ;; get RTC hours
1389 xor eax, eax
1390 mov al, 4
1391 out CMOS_ADDR, al
1392 in al, CMOS_DATA ; RTC hours, in BCD
1393 call bcd_to_bin ; eax now has hours in binary
1394 mov edx, 65543427
1395 mul edx
1396 mov ebx, 1000
1397 xor edx, edx
1398 div ebx
1399 add ecx, eax ; add to total ticks
1400
1401 mov ds:[46Ch], ecx ; timer tick count
1402 xor al, al ; TODO: redundant?
1403 mov ds:[470h], al ; rollover flag
1404 .286
1405endif
1406 ret
1407
1408rtc_post endp
1409
1410
1411
1412;; --------------------------------------------------------
1413;; INT 0Eh handler - Diskette IRQ 6 ISR
1414;; --------------------------------------------------------
1415 BIOSORG 0EF57h, 0EF55h
1416int0e_handler:
1417 push ax
1418 push dx
1419 mov dx, 3F4h
1420 in al, dx
1421 and al, 0C0h
1422 cmp al, 0C0h
1423 je int0e_normal
1424 mov dx, 3F5h
1425 mov al, 08h ; sense interrupt
1426 out dx, al
1427int0e_loop1:
1428 mov dx, 3F4h ; TODO: move out of the loop?
1429 in al, dx
1430 and al, 0C0h
1431 cmp al, 0C0h
1432 jne int0e_loop1
1433
1434int0e_loop2:
1435 mov dx, 3F5h ; TODO: inc/dec dx instead
1436 in al, dx
1437 mov dx, 3F4h
1438 in al, dx
1439 and al, 0C0h
1440 cmp al, 0C0h
1441 je int0e_loop2
1442
1443int0e_normal:
1444 push ds
1445 xor ax, ax
1446 mov ds, ax
1447 call eoi_master_pic
1448 ; indicate that an interrupt occurred
1449 or byte ptr ds:[43Eh], 80h
1450 pop ds
1451 pop dx
1452 pop ax
1453 iret
1454
1455
1456;; --------------------------------------------------------
1457;; Diskette Parameter Table
1458;; --------------------------------------------------------
1459 BIOSORG 0EFC7h, 0EFC5h
1460_diskette_param_table:
1461 db 0AFh
1462 db 2 ; HLT=1, DMA mode
1463 db 025h
1464 db 2
1465 db 18 ; SPT (good for 1.44MB media)
1466 db 01Bh
1467 db 0FFh
1468 db 06Ch
1469 db 0F6h ; format filler
1470 db 15
1471 db 8
1472
1473
1474
1475;; --------------------------------------------------------
1476;; INT 17h handler - Printer service
1477;; --------------------------------------------------------
1478 BIOSORG_CHECK 0EFD2h ; fixed WRT preceding code
1479
1480 jmp int17_handler ; NT floppy boot workaround
1481 ; see @bugref{6481}
1482int17_handler:
1483 push ds
1484 push es
1485 DO_pusha
1486 C_SETUP
1487 call _int17_function
1488 DO_popa
1489 pop es
1490 pop ds
1491 iret
1492
1493
1494
1495;; Protected mode IDT descriptor
1496;;
1497;; The limit is 0 to cause a shutdown if an exception occurs
1498;; in protected mode. TODO: Is that what we really want?
1499;;
1500;; Set base to F0000 to correspond to beginning of BIOS,
1501;; in case an IDT is defined later.
1502
1503_pmode_IDT:
1504 dw 0 ; limit 15:0
1505 dw 0 ; base 15:0
1506 dw 0Fh ; base 23:16
1507
1508
1509;; Real mode IDT descriptor
1510;;
1511;; Set to typical real-mode values.
1512;; base = 000000
1513;; limit = 03ff
1514
1515_rmode_IDT:
1516 dw 3FFh ; limit 15:00
1517 dw 0 ; base 15:00
1518 dw 0 ; base 23:16
1519
1520
1521;;
1522;; INT 1Ch
1523;;
1524;; TODO: Why does this need a special handler?
1525int1c_handler: ;; user timer tick
1526 iret
1527
1528
1529
1530;; --------------------------------------------------------
1531;; INT 10h functions 0-Fh entry point
1532;; --------------------------------------------------------
1533 BIOSORG 0F045h, 0F043h
1534i10f0f_entry:
1535 iret
1536
1537
1538;; --------------------------------------------------------
1539;; INT 10h handler - MDA/CGA video
1540;; --------------------------------------------------------
1541 BIOSORG 0F065h, 0F063h
1542int10_handler:
1543 ;; do nothing - assumes VGA
1544 iret
1545
1546
1547;; --------------------------------------------------------
1548;; MDA/CGA Video Parameter Table (INT 1Dh)
1549;; --------------------------------------------------------
1550 BIOSORG 0F0A4h, 0F0A2h
1551mdacga_vpt:
1552
1553
1554;;
1555;; INT 18h - boot failure
1556;;
1557int18_handler:
1558 C_SETUP
1559 call _int18_panic_msg
1560 ;; TODO: handle failure better?
1561 hlt
1562 iret
1563
1564;;
1565;; INT 19h - boot service - relocated
1566;;
1567int19_relocated:
1568; If an already booted OS calls int 0x19 to reboot, it is not sufficient
1569; just to try booting from the configured drives. All BIOS variables and
1570; interrupt vectors need to be reset, otherwise strange things may happen.
1571; The approach used is faking a warm reboot (which just skips showing the
1572; logo), which is a bit more than what we need, but hey, it's fast.
1573 mov bp, sp
1574 mov ax, [bp+2] ; TODO: redundant? address via sp?
1575 cmp ax, BIOSSEG ; check caller's segment
1576 jz bios_initiated_boot
1577
1578 xor ax, ax
1579 mov ds, ax
1580 mov ax, 1234h
1581 mov ds:[472], ax
1582 jmp post
1583
1584bios_initiated_boot:
1585 ;; The C worker function returns the boot drive in bl and
1586 ;; the boot segment in ax. In case of failure, the boot
1587 ;; segment will be zero.
1588 C_SETUP ; TODO: Here? Now?
1589 push bp
1590 mov bp, sp
1591
1592 ;; 1st boot device
1593 mov ax, 1
1594 push ax
1595 call _int19_function
1596 inc sp
1597 inc sp
1598 test ax, ax ; if 0, try next device
1599 jnz boot_setup
1600
1601 ;; 2nd boot device
1602 mov ax, 2
1603 push ax
1604 call _int19_function
1605 inc sp
1606 inc sp
1607 test ax, ax ; if 0, try next device
1608 jnz boot_setup
1609
1610 ; 3rd boot device
1611 mov ax, 3
1612 push ax
1613 call _int19_function
1614 inc sp
1615 inc sp
1616 test ax, ax ; if 0, try next device
1617 jnz boot_setup
1618
1619 ; 4th boot device
1620 mov ax, 4
1621 push ax
1622 call _int19_function
1623 inc sp
1624 inc sp
1625 test ax, ax ; if 0, invoke INT 18h
1626 jz int18_handler
1627
1628boot_setup:
1629; TODO: the drive should be in dl already??
1630;; mov dl, bl ; tell guest OS what boot drive is
1631if VBOX_BIOS_CPU lt 80386
1632 mov [bp], ax
1633 DO_shl ax, 4
1634 mov [bp+2], ax ; set ip
1635 mov ax, [bp]
1636else
1637 .386 ; NB: We're getting garbage into high eax bits
1638 shl eax, 4 ; convert seg to ip
1639 mov [bp+2], ax ; set ip
1640
1641 shr eax, 4 ; get cs back
1642 .286
1643endif
1644 and ax, BIOSSEG ; remove what went in ip
1645 mov [bp+4], ax ; set cs
1646 xor ax, ax
1647 mov ds, ax
1648 mov es, ax
1649 mov [bp], ax ; TODO: what's this?!
1650 mov ax, 0AA55h ; set ok flag ; TODO: and this?
1651
1652 pop bp ; TODO: why'd we just zero it??
1653 iret ; beam me up scotty
1654
1655;; PCI BIOS
1656
1657include pcibios.inc
1658include pirq.inc
1659
1660
1661;; --------------------------------------------------------
1662;; INT 12h handler - Memory size
1663;; --------------------------------------------------------
1664 BIOSORG 0F841h, 0F83Fh
1665int12_handler:
1666 ;; Don't touch - fixed size!
1667 sti
1668 push ds
1669 mov ax, 40h
1670 mov ds, ax
1671 mov ax, ds:[13h]
1672 pop ds
1673 iret
1674
1675
1676;; --------------------------------------------------------
1677;; INT 11h handler - Equipment list service
1678;; --------------------------------------------------------
1679 BIOSORG_CHECK 0F84Dh ; fixed wrt preceding code
1680int11_handler:
1681 ;; Don't touch - fixed size!
1682 sti
1683 push ds
1684 mov ax, 40h
1685 mov ds, ax
1686 mov ax, ds:[10h]
1687 pop ds
1688 iret
1689
1690
1691;; --------------------------------------------------------
1692;; INT 15h handler - System services
1693;; --------------------------------------------------------
1694 BIOSORG_CHECK 0F859h ; fixed wrt preceding code
1695int15_handler:
1696
1697if VBOX_BIOS_CPU ge 80286
1698 cmp ah, 87h
1699 jne not_blkmove
1700
1701 ;; INT 15h/87h has semi-public interface because software
1702 ;; may use CMOS shutdown status code 9 for its own purposes.
1703 ;; The stack layout has to match.
1704 pusha
1705 push es
1706 push ds
1707 C_SETUP
1708 call _int15_blkmove
1709 pop ds
1710 pop es
1711 popa
1712 iret
1713not_blkmove:
1714
1715endif
1716
1717 pushf
1718 push ds
1719 push es
1720 C_SETUP
1721 cmp ah, 86h
1722 je int15_handler32
1723 cmp ah, 0E8h
1724 je int15_handler32
1725 cmp ah, 0d0h
1726 je int15_handler32
1727 DO_pusha
1728 cmp ah, 53h ; APM function?
1729 je apm_call
1730 cmp ah, 0C2h ; PS/2 mouse function?
1731 je int15_handler_mouse
1732
1733 call _int15_function
1734int15_handler_popa_ret:
1735 DO_popa
1736int15_handler32_ret:
1737 pop es
1738 pop ds
1739 popf
1740 jmp iret_modify_cf
1741
1742apm_call:
1743 call _apm_function
1744 jmp int15_handler_popa_ret
1745
1746int15_handler_mouse:
1747 call _int15_function_mouse
1748 jmp int15_handler_popa_ret
1749
1750int15_handler32:
1751if VBOX_BIOS_CPU ge 80386
1752 ;; need to save/restore 32-bit registers
1753 .386
1754 pushad
1755 call _int15_function32
1756 popad
1757 .286
1758else
1759 DO_pusha
1760 call _int15_function32
1761 DO_popa
1762endif
1763 jmp int15_handler32_ret
1764
1765;;
1766;; Perform an IRET but retain the current carry flag value
1767;;
1768iret_modify_cf:
1769 jc carry_set
1770 push bp
1771 mov bp, sp
1772 and byte ptr [bp + 6], 0FEh
1773 or word ptr [bp + 6], 0200h
1774 pop bp
1775 iret
1776carry_set:
1777 push bp
1778 mov bp, sp
1779 or word ptr [bp + 6], 0201h
1780 pop bp
1781 iret
1782
1783;;
1784;; INT 74h handler - PS/2 mouse (IRQ 12)
1785;;
1786int74_handler proc
1787
1788 sti
1789 DO_pusha
1790 push es
1791 push ds
1792 xor ax, ax
1793 push ax ; placeholder for status
1794 push ax ; placeholder for X
1795 push ax ; placeholder for Y
1796 push ax ; placeholder for Z
1797 push ax ; placeholder for make_far_call bool
1798 C_SETUP
1799 call _int74_function
1800 pop cx ; pop make_far_call flag
1801 jcxz int74_done
1802
1803 ;; make far call to EBDA:0022
1804if VBOX_BIOS_CPU ge 80186
1805 push 0
1806else
1807 xor ax, ax
1808 push ax
1809endif
1810 pop ds
1811 push ds:[40Eh]
1812 pop ds
1813 call far ptr ds:[22h]
1814int74_done:
1815 cli
1816 call eoi_both_pics
1817 add sp, 8 ; remove status, X, Y, Z
1818 pop ds
1819 pop es
1820 DO_popa
1821 iret
1822
1823int74_handler endp
1824
1825int76_handler proc
1826
1827 ;; record completion in BIOS task complete flag
1828 push ax
1829 push ds
1830 mov ax, 40h
1831 mov ds, ax
1832 mov byte ptr ds:[8Eh], 0FFh
1833 call eoi_both_pics
1834 pop ds
1835 pop ax
1836 iret
1837
1838int76_handler endp
1839
1840
1841;;
1842;; IRQ 8 handler (RTC)
1843;;
1844int70_handler:
1845 push es
1846 push ds
1847 DO_pusha
1848 C_SETUP
1849 call _int70_function
1850 DO_popa
1851 pop ds
1852 pop es
1853 iret
1854
1855
1856
1857if VBOX_BIOS_CPU lt 80386
1858;
1859; We're tight on space down below in the int08_handler, so put
1860; the 16-bit rollover code here.
1861;
1862int08_maybe_rollover:
1863 ja int08_rollover
1864 cmp ax, 00B0h
1865 jb int08_rollover_store
1866 ;; there has been a midnight rollover
1867int08_rollover:
1868 xor dx, dx
1869 xor ax, ax
1870
1871 inc byte ptr ds:[70h] ; increment rollover flag
1872int08_rollover_store:
1873 jmp int08_store_ticks
1874endif
1875
1876
1877;; --------------------------------------------------------
1878;; 8x8 font (first 128 characters)
1879;; --------------------------------------------------------
1880 BIOSORG 0FA6Eh, 0FA6Ch
1881include font8x8.inc
1882
1883
1884;; --------------------------------------------------------
1885;; INT 1Ah handler - Time of the day + PCI BIOS
1886;; --------------------------------------------------------
1887 BIOSORG_CHECK 0FE6Eh ; fixed wrt preceding table
1888int1a_handler:
1889if VBOX_BIOS_CPU ge 80386
1890 cmp ah, 0B1h
1891 jne int1a_normal
1892
1893 push es
1894 push ds
1895 C_SETUP
1896 .386
1897 pushad
1898 call _pci16_function
1899 popad
1900 .286
1901 pop ds
1902 pop es
1903 iret
1904endif
1905
1906int1a_normal:
1907 push es
1908 push ds
1909 DO_pusha
1910 C_SETUP
1911int1a_callfunction:
1912 call _int1a_function
1913 DO_popa
1914 pop ds
1915 pop es
1916 iret
1917
1918
1919;; --------------------------------------------------------
1920;; Timer tick - IRQ 0 handler
1921;; --------------------------------------------------------
1922 BIOSORG 0FEA5h, 0FEA3h
1923int08_handler:
1924if VBOX_BIOS_CPU ge 80386
1925 .386
1926 sti
1927 push eax
1928else
1929 sti
1930 push ax
1931endif
1932 push ds
1933 push dx
1934 mov ax, 40h
1935 mov ds, ax
1936
1937if VBOX_BIOS_CPU ge 80386
1938 mov eax, ds:[6Ch] ; get ticks dword
1939 inc eax
1940else
1941 mov ax, ds:[6Ch] ; get ticks dword
1942 mov dx, ds:[6Ch+2]
1943 inc ax ; inc+jz+inc saves two bytes over add+adc.
1944 jnz int08_compare
1945 inc dx
1946int08_compare:
1947endif
1948
1949 ;; compare eax to one day's worth of ticks (at 18.2 Hz)
1950if VBOX_BIOS_CPU ge 80386
1951 cmp eax, 1800B0h
1952 jb int08_store_ticks
1953else
1954 cmp dx, 18h
1955 jb int08_store_ticks
1956 jmp int08_maybe_rollover
1957endif
1958
1959if VBOX_BIOS_CPU ge 80386
1960 ;; there has been a midnight rollover
1961 xor eax, eax
1962 inc byte ptr ds:[70h] ; increment rollover flag
1963
1964int08_store_ticks:
1965 mov ds:[6Ch], eax
1966else
1967int08_store_ticks:
1968 mov ds:[6Ch], ax
1969 mov ds:[6Ch+2], dx
1970endif
1971
1972 ;; time to turn off floppy drive motor(s)?
1973 mov al, ds:[40h]
1974 or al, al
1975 jz int08_floppy_off
1976 dec al
1977 mov ds:[40h], al
1978 jnz int08_floppy_off
1979 ;; turn motor(s) off
1980 mov dx, 03F2h
1981 in al, dx
1982 and al, 0CFh
1983 out dx, al
1984int08_floppy_off:
1985
1986 int 1Ch ; call the user timer handler
1987
1988 cli
1989 call eoi_master_pic
1990 pop dx
1991 pop ds
1992if VBOX_BIOS_CPU ge 80386
1993 pop eax
1994 .286
1995else
1996 pop ax
1997endif
1998 iret
1999
2000
2001;; --------------------------------------------------------
2002;; Initial interrupt vector offsets for POST
2003;; --------------------------------------------------------
2004 BIOSORG 0FEF3h, 0FEF1h
2005vector_table:
2006
2007
2008
2009;; --------------------------------------------------------
2010;; BIOS copyright string
2011;; --------------------------------------------------------
2012 BIOSORG 0FF00h, 0FEFEh
2013bios_string:
2014 db BIOS_COPYRIGHT
2015
2016
2017;; --------------------------------------------------------
2018;; IRET - default interrupt handler
2019;; --------------------------------------------------------
2020 BIOSORG 0FF53h, 0FF51h
2021
2022dummy_iret:
2023 iret
2024
2025
2026;; --------------------------------------------------------
2027;; INT 05h - Print Screen service
2028;; --------------------------------------------------------
2029 BIOSORG_CHECK 0FF54h ; fixed wrt preceding
2030int05_handler:
2031 ;; Not implemented
2032 iret
2033
2034include smidmi.inc
2035
2036;; --------------------------------------------------------
2037;; Processor reset entry point
2038;; --------------------------------------------------------
2039 BIOSORG 0FFF0h, 0FFEEh
2040cpu_reset:
2041 ;; This is where the CPU starts executing after a reset
2042 jmp far ptr post
2043
2044 ;; BIOS build date
2045 db BIOS_BUILD_DATE
2046 db 0 ; padding
2047 ;; System model ID
2048 db SYS_MODEL_ID
2049 ;; Checksum byte
2050 db 0FFh
2051
2052
2053BIOSSEG ends
2054
2055 end
2056
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette