VirtualBox

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

Last change on this file since 68137 was 67888, checked in by vboxsync, 8 years ago

BIOS: Typo (IRQ 10 and 11 both should have the dummy handler).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 64.0 KB
Line 
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.virtualbox.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 ;; INT 41h/46h: hard disk 0/1 dpt
585 ; TODO: This should be done from the code which
586 ; builds the DPTs?
587 SET_INT_VECTOR 41h, EBDA_SEG, 3Dh
588 SET_INT_VECTOR 46h, EBDA_SEG, 4Dh
589 ret
590
591hard_drive_post endp
592
593
594norm_post_cont:
595 ;; PS/2 mouse setup
596 SET_INT_VECTOR 74h, BIOSSEG, int74_handler
597
598 ;; IRQ 13h (FPU exception) setup
599 SET_INT_VECTOR 75h, BIOSSEG, int75_handler
600
601 call init_pic
602
603 C_SETUP
604
605if VBOX_BIOS_CPU ge 80386
606 ;; Set up local APIC
607 .386
608 pushad
609 call _apic_setup
610 popad
611 SET_DEFAULT_CPU_286
612endif
613
614 ;; ATA/ATAPI driver setup
615 call _ata_init
616 call _ata_detect
617
618ifdef VBOX_WITH_AHCI
619 ; AHCI driver setup
620 call _ahci_init
621endif
622
623ifdef VBOX_WITH_SCSI
624 ; SCSI driver setup
625 call _scsi_init
626endif
627
628 ;; floppy setup
629 call floppy_post
630
631 ;; hard drive setup
632 call hard_drive_post
633
634 C_SETUP ; in case assembly code changed things
635 ;; Scan for additional ROMs in the C800-EFFF range
636 mov ax, 0C800h
637 mov dx, 0F000h
638 call rom_scan_
639
640if VBOX_BIOS_CPU ge 80386
641 ;; The POST code does not bother preserving high bits of the
642 ;; 32-bit registers. Now is a good time to clear them so that
643 ;; there's no garbage left in high bits.
644 .386
645 xor eax, eax
646 xor ebx, ebx
647 xor ecx, ecx
648 xor edx, edx
649 .286
650endif
651
652 call _print_bios_banner
653
654 ;; El Torito floppy/hard disk emulation
655 call _cdemu_init
656
657 ; TODO: what's the point of enabling interrupts here??
658 sti ; enable interrupts
659 int 19h
660 ;; does not return here
661 sti
662wait_forever:
663 hlt
664 jmp wait_forever
665 cli
666 hlt
667
668
669;;
670;; Return from block move (shutdown code 09h). Care must be taken to disturb
671;; register and memory state as little as possible.
672;;
673return_blkmove:
674 .286p
675 mov ax, 40h
676 mov ds, ax
677 ;; restore user stack
678 mov ss, ds:[69h]
679 mov sp, ds:[67h]
680 ;; reset A20 gate
681 in al, 92h
682 and al, 0FDh
683 out 92h, al
684 ;; ensure proper real mode IDT
685 lidt fword ptr cs:_rmode_IDT
686 ;; restore user segments
687 pop ds
688 pop es
689 ;; set up BP
690 mov bp, sp
691 ;; restore status code
692 in al, 80h
693 mov [bp+15], al
694 ;; set ZF/CF
695 cmp ah,al ; AH is zero here!
696 ;; restore registers and return
697 popa
698 sti
699 retf 2
700 SET_DEFAULT_CPU_286
701
702
703;; --------------------------------------------------------
704;; INT 13h handler - Disk services
705;; --------------------------------------------------------
706 BIOSORG 0E3FEh, 0E3FCh
707
708int13_handler:
709 jmp int13_relocated
710
711
712;; --------------------------------------------------------
713;; Fixed Disk Parameter Table
714;; --------------------------------------------------------
715 BIOSORG_CHECK 0E401h ; fixed wrt preceding
716
717rom_fdpt:
718
719;; --------------------------------------------------------
720;; INT 19h handler - Boot load service
721;; --------------------------------------------------------
722 BIOSORG 0E6F2h, 0E6F0h
723
724int19_handler:
725 jmp int19_relocated
726
727
728
729;; --------------------------------------------------------
730;; System BIOS Configuration Table
731;; --------------------------------------------------------
732 BIOSORG_CHECK 0E6F5h ; fixed wrt preceding
733; must match BIOS_CONFIG_TABLE
734bios_cfg_table:
735 dw 9 ; table size in bytes
736 db SYS_MODEL_ID
737 db SYS_SUBMODEL_ID
738 db BIOS_REVISION
739 ; Feature byte 1
740 ; b7: 1=DMA channel 3 used by hard disk
741 ; b6: 1=2 interrupt controllers present
742 ; b5: 1=RTC present
743 ; b4: 1=BIOS calls int 15h/4Fh for every key
744 ; b3: 1=wait for extern event supported (Int 15h/41h)
745 ; b2: 1=extended BIOS data area used
746 ; b1: 0=AT or ESDI bus, 1=MicroChannel
747 ; b0: 1=Dual bus (MicroChannel + ISA)
748ifdef BX_CALL_INT15_4F
749 db 74h; or USE_EBDA
750else
751 db 64h; or USE_EBDA
752endif
753 ; Feature byte 2
754 ; b7: 1=32-bit DMA supported
755 ; b6: 1=int16h, function 9 supported
756 ; b5: 1=int15h/C6h (get POS data) supported
757 ; b4: 1=int15h/C7h (get mem map info) supported
758 ; b3: 1=int15h/C8h (en/dis CPU) supported
759 ; b2: 1=non-8042 kb controller
760 ; b1: 1=data streaming supported
761 ; b0: reserved
762 db 40h
763 ; Feature byte 3
764 ; b7: not used
765 ; b6: reserved
766 ; b5: reserved
767 ; b4: POST supports ROM-to-RAM enable/disable
768 ; b3: SCSI on system board
769 ; b2: info panel installed
770 ; b1: Initial Machine Load (IML) system - BIOS on disk
771 ; b0: SCSI supported in IML
772 db 0
773 ; Feature byte 4
774 ; b7: IBM private
775 ; b6: EEPROM present
776 ; b5-3: ABIOS presence (011 = not supported)
777 ; b2: private
778 ; b1: memory split above 16Mb supported
779 ; b0: POSTEXT directly supported by POST
780 db 0
781 ; Feature byte 5 (IBM)
782 ; b1: enhanced mouse
783 ; b0: flash EPROM
784 db 0
785
786
787;; --------------------------------------------------------
788;; Baud Rate Generator Table
789;; --------------------------------------------------------
790 BIOSORG 0E729h, 0E727h
791
792
793;; --------------------------------------------------------
794;; INT 14h handler - Serial Communication Service
795;; --------------------------------------------------------
796 BIOSORG 0E739h, 0E737h
797int14_handler:
798 push ds
799 push es
800 DO_pusha
801 C_SETUP
802 call _int14_function
803 DO_popa
804 pop es
805 pop ds
806 iret
807
808
809
810;;
811;; Handler for unexpected hardware interrupts
812;;
813dummy_isr:
814 push ds
815 push es
816 DO_pusha
817 C_SETUP
818 call _dummy_isr_function
819 DO_popa
820 pop es
821 pop ds
822 iret
823
824
825init_pic proc near
826
827 mov al, 11h ; send init commands
828 out PIC_MASTER, al
829 out PIC_SLAVE, al
830 mov al, 08h ; base 08h
831 out PIC_MASTER+1, al
832 mov al, 70h ; base 70h
833 out PIC_SLAVE+1, al
834 mov al, 04h ; master PIC
835 out PIC_MASTER+1, al
836 mov al, 02h ; slave PIC
837 out PIC_SLAVE+1, al
838 mov al, 01h
839 out PIC_MASTER+1, al
840 out PIC_SLAVE+1, al
841 mov al, 0B8h ; unmask IRQs 0/1/2/6
842 out PIC_MASTER+1, al
843 mov al, 08Fh
844 out PIC_SLAVE+1, al ; unmask IRQs 12/13/14
845 ret
846
847init_pic endp
848
849ebda_post proc near
850
851 SET_INT_VECTOR 0Dh, BIOSSEG, dummy_isr ; IRQ 5
852 SET_INT_VECTOR 0Fh, BIOSSEG, dummy_isr ; IRQ 7
853 SET_INT_VECTOR 72h, BIOSSEG, dummy_isr ; IRQ 10
854 SET_INT_VECTOR 73h, BIOSSEG, dummy_isr ; IRQ 11
855 SET_INT_VECTOR 77h, BIOSSEG, dummy_isr ; IRQ 15
856
857 mov ax, EBDA_SEG
858 mov ds, ax
859 mov byte ptr ds:[0], EBDA_SIZE
860 ;; store EBDA seg in 40:0E
861 xor ax, ax
862 mov ds, ax
863 mov word ptr ds:[40Eh], EBDA_SEG
864 ret
865
866ebda_post endp
867
868
869
870;; --------------------------------------------------------
871;; INT 16h handler - Keyboard service
872;; --------------------------------------------------------
873 BIOSORG 0E82Eh, 0E82Ch
874int16_handler:
875 sti
876 ;; Flags are saved *after* enabling interrupts, and with
877 ;; implicitly cleared TF. Software may depend on that.
878 pushf
879 push es
880 push ds
881 DO_pusha
882
883 cmp ah, 0
884 je int16_F00
885
886 cmp ah, 10h
887 je int16_F00
888
889 C_SETUP
890 call _int16_function
891 DO_popa
892 pop ds
893 pop es
894 add sp, 2 ; Skip saved flags
895 iret
896
897int16_F00:
898 mov bx, 40h ; TODO: why 40h here and 0 elsewhere?
899 mov ds, bx
900int16_wait_for_key:
901 cli
902 mov bx, ds:[1Ah]
903 cmp bx, ds:[1Ch]
904 jne int16_key_found
905 sti
906 nop
907; TODO: review/enable?
908if 0
909 push ax
910 mov ax, 9002h
911 int 15h
912 pop ax
913endif
914 jmp int16_wait_for_key
915
916int16_key_found:
917 C_SETUP
918 call _int16_function
919 DO_popa
920 pop ds
921 pop es
922 add sp, 2 ; Skip saved flags
923; TODO: review/enable? If so, flags should be restored here?
924if 0
925 push ax
926 mov ax, 9202h
927 int 15h
928 pop ax
929endif
930 iret
931
932
933if VBOX_BIOS_CPU ge 80386
934;; Quick and dirty protected mode entry/exit routines
935include pmode.inc
936
937;; Initialization code which needs to run in protected mode (LAPIC etc.)
938include pmsetup.inc
939endif
940
941
942KBDC_DISABLE EQU 0ADh
943KBDC_ENABLE EQU 0AEh
944KBC_CMD EQU 64h
945KBC_DATA EQU 60h
946
947;; --------------------------------------------------------
948;; INT 09h handler - Keyboard ISR (IRQ 1)
949;; --------------------------------------------------------
950 BIOSORG 0E987h, 0E985h
951int09_handler:
952 cli ; TODO: why? they're off already!
953 push ax
954 mov al, KBDC_DISABLE
955 out KBC_CMD, al
956
957 in al, KBC_DATA
958 push ds
959 DO_pusha
960 cld ; Before INT 15h (and any C code)
961ifdef BX_CALL_INT15_4F
962 mov ah, 4Fh
963 stc
964 int 15h ; keyboard intercept
965 jnc int09_done
966endif
967 sti ; Only after calling INT 15h
968
969 ;; check for extended key
970 cmp al, 0E0h
971 jne int09_check_pause
972 xor ax, ax
973 mov ds, ax
974 or byte ptr ds:[496h], 2 ; mf2_state |= 0x02
975 jmp int09_done
976
977int09_check_pause:
978 cmp al, 0E1h ; pause key?
979 jne int09_process_key
980 xor ax, ax
981 mov ds, ax
982 or byte ptr ds:[496h], 1 ; mf2_state | 0x01
983 jmp int09_done
984
985int09_process_key:
986 push es
987 C_SETUP
988 call _int09_function
989 pop es
990
991int09_done:
992 DO_popa
993 pop ds
994 cli
995 call eoi_master_pic
996
997 mov al, KBDC_ENABLE
998 out KBC_CMD, al
999 pop ax
1000 iret
1001
1002
1003;; --------------------------------------------------------
1004;; INT 06h handler - Invalid Opcode Exception
1005;; --------------------------------------------------------
1006
1007int06_handler:
1008 DO_pusha
1009 push es
1010 push ds
1011 C_SETUP
1012 call _inv_op_handler
1013 pop ds
1014 pop es
1015 DO_popa
1016 iret
1017
1018;; --------------------------------------------------------
1019;; INT 13h handler - Diskette service
1020;; --------------------------------------------------------
1021 BIOSORG 0EC59h, 0EC57h
1022int13_diskette:
1023 jmp int13_noeltorito
1024
1025
1026
1027;; --------------------------------------------------------
1028;; INT 13h handler - Disk service
1029;; --------------------------------------------------------
1030int13_relocated:
1031 ;; check for an El-Torito function
1032 cmp ah, 4Ah
1033 jb int13_not_eltorito
1034
1035 cmp ah, 4Dh
1036 ja int13_not_eltorito
1037
1038 DO_pusha
1039 push es
1040 push ds
1041 C_SETUP ; TODO: setup C envrionment only once?
1042 DO_JMP_CALL_EX _int13_eltorito, int13_out, jmp_call_ret_int13_out ; ELDX not used
1043if VBOX_BIOS_CPU eq 8086
1044jmp_call_ret_int13_out: dw offset int13_out
1045endif
1046
1047int13_not_eltorito:
1048 push es
1049 push ax ; TODO: better register save/restore
1050 push bx
1051 push cx
1052 push dx
1053
1054 ;; check if emulation is active
1055 call _cdemu_isactive
1056 cmp al, 0
1057 je int13_cdemu_inactive
1058
1059 ;; check if access to the emulated drive
1060 call _cdemu_emulated_drive
1061 pop dx ; recover dx (destroyed by C code)
1062 push dx
1063 cmp al, dl ; INT 13h on emulated drive
1064 jne int13_nocdemu
1065
1066 pop dx
1067 pop cx
1068 pop bx
1069 pop ax
1070 pop es
1071
1072 DO_pusha
1073 push es
1074 push ds
1075 C_SETUP ; TODO: setup environment only once?
1076
1077 DO_JMP_CALL_EX _int13_cdemu, int13_out, jmp_call_ret_int13_out ; ELDX not used
1078
1079int13_nocdemu:
1080 and dl, 0E0h ; mask to get device class
1081 cmp al, dl
1082 jne int13_cdemu_inactive
1083
1084 pop dx
1085 pop cx
1086 pop bx
1087 pop ax
1088 pop es
1089
1090 push ax
1091 push cx
1092 push dx
1093 push bx
1094
1095 dec dl ; real drive is dl - 1
1096 jmp int13_legacy
1097
1098int13_cdemu_inactive:
1099 pop dx
1100 pop cx
1101 pop bx
1102 pop ax
1103 pop es
1104
1105int13_noeltorito:
1106 push ax
1107 push cx
1108 push dx
1109 push bx
1110int13_legacy:
1111 push dx ; push eltorito dx in place of sp
1112 push bp
1113 push si
1114 push di
1115 push es
1116 push ds
1117 C_SETUP ; TODO: setup environment only once?
1118
1119 ;; now the registers can be restored with
1120 ;; pop ds; pop es; DO_popa; iret
1121 test dl, 80h ; non-removable?
1122 jnz int13_notfloppy
1123
1124 DO_JMP_CALL_EX _int13_diskette_function, int13_out, jmp_call_ret_int13_out
1125
1126int13_notfloppy:
1127 cmp dl, 0E0h
1128 jb int13_notcdrom
1129
1130 ;; ebx may be modified, save here
1131 ;; TODO: check/review 32-bit register use
1132 ;; @todo figure if 80286/8086 variant is applicable.
1133 .386
1134 shr ebx, 16
1135 push bx
1136 call _int13_cdrom
1137 pop bx
1138 shl ebx, 16
1139 SET_DEFAULT_CPU_286
1140 jmp int13_out
1141
1142int13_notcdrom:
1143int13_disk:
1144 cmp ah,40h
1145 ja int13x
1146 call _int13_harddisk
1147 jmp int13_out
1148
1149int13x:
1150 call _int13_harddisk_ext
1151
1152int13_out:
1153 pop ds
1154 pop es
1155 DO_popa
1156 iret
1157
1158
1159
1160; parallel port detection: port in dx, index in bx, timeout in cl
1161detect_parport proc near
1162
1163 push dx
1164 inc dx
1165 inc dx
1166 in al, dx
1167 and al, 0DFh ; clear input mode
1168 out dx, al
1169 pop dx
1170 mov al, 0AAh
1171 out dx, al
1172 in al, dx
1173 cmp al, 0AAh
1174 jne no_parport
1175
1176 push bx
1177 shl bx, 1
1178 mov [bx+408h], dx ; parallel I/O address
1179 pop bx
1180 mov [bx+478h], cl ; parallel printer timeout
1181 inc bx
1182no_parport:
1183 ret
1184
1185detect_parport endp
1186
1187; setial port detection: port in dx, index in bx, timeout in cl
1188detect_serial proc near
1189
1190 push dx
1191 inc dx
1192 mov al, 2
1193 out dx, al
1194 in al, dx
1195 cmp al, 2
1196 jne no_serial
1197
1198 inc dx
1199 in al, dx
1200 cmp al, 2
1201 jne no_serial
1202
1203 dec dx
1204 xor al, al
1205 pop dx
1206 push bx
1207 shl bx, 1
1208 mov [bx+400h], dx ; serial I/O address
1209 pop bx
1210 mov [bx+47Ch], cl ; serial timeout
1211 inc bx
1212 ret
1213
1214no_serial:
1215 pop dx
1216 ret
1217
1218detect_serial endp
1219
1220
1221;;
1222;; POST: Floppy drive
1223;;
1224floppy_post proc near
1225
1226 xor ax, ax
1227 mov ds, ax
1228
1229 ;; TODO: This code is really stupid. Zeroing the BDA byte
1230 ;; by byte is dumb, and it's been already zeroed elsewhere!
1231 mov al, 0
1232 mov ds:[43Eh], al ; drive 0/1 uncalibrated, no IRQ
1233 mov ds:[43Fh], al ; motor status
1234 mov ds:[440h], al ; motor timeout counter
1235 mov ds:[441h], al ; controller status return code
1236 mov ds:[442h], al ; hd/floppy ctlr status register
1237 mov ds:[443h], al ; controller status register 1
1238 mov ds:[444h], al ; controller status register 2
1239 mov ds:[445h], al ; cylinder number
1240 mov ds:[446h], al ; head number
1241 mov ds:[447h], al ; sector number
1242 mov ds:[448h], al ; bytes written
1243
1244 mov ds:[48Bh], al ; configuration data
1245
1246 mov al, 10h ; floppy drive type
1247 out CMOS_ADDR, al
1248 in al, CMOS_DATA
1249 mov ah, al ; save drive type byte
1250
1251look_drive0:
1252 ; TODO: pre-init bl to reduce jumps
1253 DO_shr al, 4 ; drive 0 in high nibble
1254 jz f0_missing ; jump if no drive
1255 mov bl, 7 ; drv0 determined, multi-rate, chgline
1256 jmp look_drive1
1257
1258f0_missing:
1259 mov bl, 0 ; no drive 0
1260
1261look_drive1:
1262 mov al, ah ; restore CMOS data
1263 and al, 0Fh ; drive 1 in low nibble
1264 jz f1_missing
1265 or bl, 70h ; drv1 determined, multi-rate, chgline
1266f1_missing:
1267 mov ds:[48Fh], bl ; store in BDA
1268
1269 ;; TODO: See above. Dumb *and* redundant!
1270 mov al, 0
1271 mov ds:[490h], al ; drv0 media state
1272 mov ds:[491h], al ; drv1 media state
1273 mov ds:[492h], al ; drv0 operational state
1274 mov ds:[493h], al ; drv1 operational state
1275 mov ds:[494h], al ; drv0 current cylinder
1276 mov ds:[495h], al ; drv1 current cylinder
1277
1278 mov al, 2
1279 out 0Ah, al ; unmask DMA channel 2
1280
1281 SET_INT_VECTOR 1Eh, BIOSSEG, _diskette_param_table
1282 SET_INT_VECTOR 40h, BIOSSEG, int13_diskette
1283 SET_INT_VECTOR 0Eh, BIOSSEG, int0e_handler ; IRQ 6
1284
1285 ret
1286
1287floppy_post endp
1288
1289
1290bcd_to_bin proc near
1291
1292 ;; in : AL in packed BCD format
1293 ;; out: AL in binary, AH always 0
1294if VBOX_BIOS_CPU ge 80186
1295 shl ax, 4
1296 shr al, 4
1297else
1298 push cx
1299 mov cl, 4
1300 shl ax, cl
1301 shr al, cl
1302 pop cx
1303endif
1304 aad
1305 ret
1306
1307bcd_to_bin endp
1308
1309rtc_post proc near
1310
1311if VBOX_BIOS_CPU lt 80386 ;; @todo fix loopy code below
1312 ;; get RTC seconds
1313 mov al, 0
1314 out CMOS_ADDR, al
1315 in al, CMOS_DATA ; RTC seconds, in BCD
1316 call bcd_to_bin ; ax now has seconds in binary
1317 test al, al
1318 xor ah, ah
1319 mov dx, 0x1234 ; 18206507*0x100/1000000 = 0x1234 (4660.865792)
1320 mul dx
1321 mov cx, ax ; tick count in dx:cx
1322
1323 ;; get RTC minutes
1324 mov al, 2
1325 out CMOS_ADDR, al
1326 in al, CMOS_DATA ; RTC minutes, in BCD
1327 call bcd_to_bin ; eax now has minutes in binary
1328 test al, al
1329 jz rtc_post_hours
1330rtc_pos_min_loop: ; 18206507*60*0x100/1000000 = 0x44463 (279651.94752)
1331 add cx, 0x4463
1332 adc dx, 0x0004
1333 dec al
1334 jnz rtc_pos_min_loop
1335
1336 ;; get RTC hours
1337rtc_post_hours:
1338 mov al, 4
1339 out CMOS_ADDR, al
1340 in al, CMOS_DATA ; RTC hours, in BCD
1341 call bcd_to_bin ; eax now has hours in binary
1342 test al, al
1343 jz rtc_pos_shift
1344rtc_pos_hour_loop: ; 18206507*3600*0x100/1000000 = 0x100076C (16779116.8512)
1345 add cx, 0x076C
1346 adc dx, 0x0100
1347 dec al
1348 jnz rtc_pos_hour_loop
1349
1350rtc_pos_shift:
1351 mov cl, ch
1352 mov ch, dl
1353 mov dl, dh
1354 xor dh, dh
1355 mov ds:[46Ch], cx ; timer tick count
1356 mov ds:[46Ch+2], dx ; timer tick count
1357 mov ds:[470h], dh ; rollover flag
1358
1359else
1360 .386
1361 ;; get RTC seconds
1362 xor eax, eax
1363 mov al, 0
1364 out CMOS_ADDR, al
1365 in al, CMOS_DATA ; RTC seconds, in BCD
1366 call bcd_to_bin ; eax now has seconds in binary
1367 mov edx, 18206507
1368 mul edx
1369 mov ebx, 1000000
1370 xor edx, edx
1371 div ebx
1372 mov ecx, eax ; total ticks in ecx
1373
1374 ;; get RTC minutes
1375 xor eax, eax
1376 mov al, 2
1377 out CMOS_ADDR, al
1378 in al, CMOS_DATA ; RTC minutes, in BCD
1379 call bcd_to_bin ; eax now has minutes in binary
1380 mov edx, 10923904
1381 mul edx
1382 mov ebx, 10000
1383 xor edx, edx
1384 div ebx
1385 add ecx, eax ; add to total ticks
1386
1387 ;; get RTC hours
1388 xor eax, eax
1389 mov al, 4
1390 out CMOS_ADDR, al
1391 in al, CMOS_DATA ; RTC hours, in BCD
1392 call bcd_to_bin ; eax now has hours in binary
1393 mov edx, 65543427
1394 mul edx
1395 mov ebx, 1000
1396 xor edx, edx
1397 div ebx
1398 add ecx, eax ; add to total ticks
1399
1400 mov ds:[46Ch], ecx ; timer tick count
1401 xor al, al ; TODO: redundant?
1402 mov ds:[470h], al ; rollover flag
1403 .286
1404endif
1405 ret
1406
1407rtc_post endp
1408
1409
1410
1411;; --------------------------------------------------------
1412;; INT 0Eh handler - Diskette IRQ 6 ISR
1413;; --------------------------------------------------------
1414 BIOSORG 0EF57h, 0EF55h
1415int0e_handler:
1416 push ax
1417 push dx
1418 mov dx, 3F4h
1419 in al, dx
1420 and al, 0C0h
1421 cmp al, 0C0h
1422 je int0e_normal
1423 mov dx, 3F5h
1424 mov al, 08h ; sense interrupt
1425 out dx, al
1426int0e_loop1:
1427 mov dx, 3F4h ; TODO: move out of the loop?
1428 in al, dx
1429 and al, 0C0h
1430 cmp al, 0C0h
1431 jne int0e_loop1
1432
1433int0e_loop2:
1434 mov dx, 3F5h ; TODO: inc/dec dx instead
1435 in al, dx
1436 mov dx, 3F4h
1437 in al, dx
1438 and al, 0C0h
1439 cmp al, 0C0h
1440 je int0e_loop2
1441
1442int0e_normal:
1443 push ds
1444 xor ax, ax
1445 mov ds, ax
1446 call eoi_master_pic
1447 ; indicate that an interrupt occurred
1448 or byte ptr ds:[43Eh], 80h
1449 pop ds
1450 pop dx
1451 pop ax
1452 iret
1453
1454
1455;; --------------------------------------------------------
1456;; Diskette Parameter Table
1457;; --------------------------------------------------------
1458 BIOSORG 0EFC7h, 0EFC5h
1459_diskette_param_table:
1460 db 0AFh
1461 db 2 ; HLT=1, DMA mode
1462 db 025h
1463 db 2
1464 db 18 ; SPT (good for 1.44MB media)
1465 db 01Bh
1466 db 0FFh
1467 db 06Ch
1468 db 0F6h ; format filler
1469 db 15
1470 db 8
1471
1472
1473
1474;; --------------------------------------------------------
1475;; INT 17h handler - Printer service
1476;; --------------------------------------------------------
1477 BIOSORG_CHECK 0EFD2h ; fixed WRT preceding code
1478
1479 jmp int17_handler ; NT floppy boot workaround
1480 ; see @bugref{6481}
1481int17_handler:
1482 push ds
1483 push es
1484 DO_pusha
1485 C_SETUP
1486 call _int17_function
1487 DO_popa
1488 pop es
1489 pop ds
1490 iret
1491
1492
1493
1494;; Protected mode IDT descriptor
1495;;
1496;; The limit is 0 to cause a shutdown if an exception occurs
1497;; in protected mode. TODO: Is that what we really want?
1498;;
1499;; Set base to F0000 to correspond to beginning of BIOS,
1500;; in case an IDT is defined later.
1501
1502_pmode_IDT:
1503 dw 0 ; limit 15:0
1504 dw 0 ; base 15:0
1505 dw 0Fh ; base 23:16
1506
1507
1508;; Real mode IDT descriptor
1509;;
1510;; Set to typical real-mode values.
1511;; base = 000000
1512;; limit = 03ff
1513
1514_rmode_IDT:
1515 dw 3FFh ; limit 15:00
1516 dw 0 ; base 15:00
1517 dw 0 ; base 23:16
1518
1519
1520;;
1521;; INT 1Ch
1522;;
1523;; TODO: Why does this need a special handler?
1524int1c_handler: ;; user timer tick
1525 iret
1526
1527
1528
1529;; --------------------------------------------------------
1530;; INT 10h functions 0-Fh entry point
1531;; --------------------------------------------------------
1532 BIOSORG 0F045h, 0F043h
1533i10f0f_entry:
1534 iret
1535
1536
1537;; --------------------------------------------------------
1538;; INT 10h handler - MDA/CGA video
1539;; --------------------------------------------------------
1540 BIOSORG 0F065h, 0F063h
1541int10_handler:
1542 ;; do nothing - assumes VGA
1543 iret
1544
1545
1546;; --------------------------------------------------------
1547;; MDA/CGA Video Parameter Table (INT 1Dh)
1548;; --------------------------------------------------------
1549 BIOSORG 0F0A4h, 0F0A2h
1550mdacga_vpt:
1551
1552
1553;;
1554;; INT 18h - boot failure
1555;;
1556int18_handler:
1557 C_SETUP
1558 call _int18_panic_msg
1559 ;; TODO: handle failure better?
1560 hlt
1561 iret
1562
1563;;
1564;; INT 19h - boot service - relocated
1565;;
1566int19_relocated:
1567; If an already booted OS calls int 0x19 to reboot, it is not sufficient
1568; just to try booting from the configured drives. All BIOS variables and
1569; interrupt vectors need to be reset, otherwise strange things may happen.
1570; The approach used is faking a warm reboot (which just skips showing the
1571; logo), which is a bit more than what we need, but hey, it's fast.
1572 mov bp, sp
1573 mov ax, [bp+2] ; TODO: redundant? address via sp?
1574 cmp ax, BIOSSEG ; check caller's segment
1575 jz bios_initiated_boot
1576
1577 xor ax, ax
1578 mov ds, ax
1579 mov ax, 1234h
1580 mov ds:[472], ax
1581 jmp post
1582
1583bios_initiated_boot:
1584 ;; The C worker function returns the boot drive in bl and
1585 ;; the boot segment in ax. In case of failure, the boot
1586 ;; segment will be zero.
1587 C_SETUP ; TODO: Here? Now?
1588 push bp
1589 mov bp, sp
1590
1591 ;; 1st boot device
1592 mov ax, 1
1593 push ax
1594 call _int19_function
1595 inc sp
1596 inc sp
1597 test ax, ax ; if 0, try next device
1598 jnz boot_setup
1599
1600 ;; 2nd boot device
1601 mov ax, 2
1602 push ax
1603 call _int19_function
1604 inc sp
1605 inc sp
1606 test ax, ax ; if 0, try next device
1607 jnz boot_setup
1608
1609 ; 3rd boot device
1610 mov ax, 3
1611 push ax
1612 call _int19_function
1613 inc sp
1614 inc sp
1615 test ax, ax ; if 0, try next device
1616 jnz boot_setup
1617
1618 ; 4th boot device
1619 mov ax, 4
1620 push ax
1621 call _int19_function
1622 inc sp
1623 inc sp
1624 test ax, ax ; if 0, invoke INT 18h
1625 jz int18_handler
1626
1627boot_setup:
1628; TODO: the drive should be in dl already??
1629;; mov dl, bl ; tell guest OS what boot drive is
1630if VBOX_BIOS_CPU lt 80386
1631 mov [bp], ax
1632 DO_shl ax, 4
1633 mov [bp+2], ax ; set ip
1634 mov ax, [bp]
1635else
1636 .386 ; NB: We're getting garbage into high eax bits
1637 shl eax, 4 ; convert seg to ip
1638 mov [bp+2], ax ; set ip
1639
1640 shr eax, 4 ; get cs back
1641 .286
1642endif
1643 and ax, BIOSSEG ; remove what went in ip
1644 mov [bp+4], ax ; set cs
1645 xor ax, ax
1646 mov ds, ax
1647 mov es, ax
1648 mov [bp], ax ; TODO: what's this?!
1649 mov ax, 0AA55h ; set ok flag ; TODO: and this?
1650
1651 pop bp ; TODO: why'd we just zero it??
1652 iret ; beam me up scotty
1653
1654;; PCI BIOS
1655
1656include pcibios.inc
1657include pirq.inc
1658
1659
1660;; --------------------------------------------------------
1661;; INT 12h handler - Memory size
1662;; --------------------------------------------------------
1663 BIOSORG 0F841h, 0F83Fh
1664int12_handler:
1665 ;; Don't touch - fixed size!
1666 sti
1667 push ds
1668 mov ax, 40h
1669 mov ds, ax
1670 mov ax, ds:[13h]
1671 pop ds
1672 iret
1673
1674
1675;; --------------------------------------------------------
1676;; INT 11h handler - Equipment list service
1677;; --------------------------------------------------------
1678 BIOSORG_CHECK 0F84Dh ; fixed wrt preceding code
1679int11_handler:
1680 ;; Don't touch - fixed size!
1681 sti
1682 push ds
1683 mov ax, 40h
1684 mov ds, ax
1685 mov ax, ds:[10h]
1686 pop ds
1687 iret
1688
1689
1690;; --------------------------------------------------------
1691;; INT 15h handler - System services
1692;; --------------------------------------------------------
1693 BIOSORG_CHECK 0F859h ; fixed wrt preceding code
1694int15_handler:
1695
1696if VBOX_BIOS_CPU ge 80286
1697 cmp ah, 87h
1698 jne not_blkmove
1699
1700 ;; INT 15h/87h has semi-public interface because software
1701 ;; may use CMOS shutdown status code 9 for its own purposes.
1702 ;; The stack layout has to match.
1703 pusha
1704 push es
1705 push ds
1706 C_SETUP
1707 call _int15_blkmove
1708 pop ds
1709 pop es
1710 popa
1711 iret
1712not_blkmove:
1713
1714endif
1715
1716 pushf
1717 push ds
1718 push es
1719 C_SETUP
1720 cmp ah, 86h
1721 je int15_handler32
1722 cmp ah, 0E8h
1723 je int15_handler32
1724 cmp ah, 0d0h
1725 je int15_handler32
1726 DO_pusha
1727 cmp ah, 53h ; APM function?
1728 je apm_call
1729 cmp ah, 0C2h ; PS/2 mouse function?
1730 je int15_handler_mouse
1731
1732 call _int15_function
1733int15_handler_popa_ret:
1734 DO_popa
1735int15_handler32_ret:
1736 pop es
1737 pop ds
1738 popf
1739 jmp iret_modify_cf
1740
1741apm_call:
1742 call _apm_function
1743 jmp int15_handler_popa_ret
1744
1745int15_handler_mouse:
1746 call _int15_function_mouse
1747 jmp int15_handler_popa_ret
1748
1749int15_handler32:
1750if VBOX_BIOS_CPU ge 80386
1751 ;; need to save/restore 32-bit registers
1752 .386
1753 pushad
1754 call _int15_function32
1755 popad
1756 .286
1757else
1758 DO_pusha
1759 call _int15_function32
1760 DO_popa
1761endif
1762 jmp int15_handler32_ret
1763
1764;;
1765;; Perform an IRET but retain the current carry flag value
1766;;
1767iret_modify_cf:
1768 jc carry_set
1769 push bp
1770 mov bp, sp
1771 and byte ptr [bp + 6], 0FEh
1772 or word ptr [bp + 6], 0200h
1773 pop bp
1774 iret
1775carry_set:
1776 push bp
1777 mov bp, sp
1778 or word ptr [bp + 6], 0201h
1779 pop bp
1780 iret
1781
1782;;
1783;; INT 74h handler - PS/2 mouse (IRQ 12)
1784;;
1785int74_handler proc
1786
1787 sti
1788 DO_pusha
1789 push es
1790 push ds
1791 xor ax, ax
1792 push ax ; placeholder for status
1793 push ax ; placeholder for X
1794 push ax ; placeholder for Y
1795 push ax ; placeholder for Z
1796 push ax ; placeholder for make_far_call bool
1797 C_SETUP
1798 call _int74_function
1799 pop cx ; pop make_far_call flag
1800 jcxz int74_done
1801
1802 ;; make far call to EBDA:0022
1803if VBOX_BIOS_CPU ge 80186
1804 push 0
1805else
1806 xor ax, ax
1807 push ax
1808endif
1809 pop ds
1810 push ds:[40Eh]
1811 pop ds
1812 call far ptr ds:[22h]
1813int74_done:
1814 cli
1815 call eoi_both_pics
1816 add sp, 8 ; remove status, X, Y, Z
1817 pop ds
1818 pop es
1819 DO_popa
1820 iret
1821
1822int74_handler endp
1823
1824int76_handler proc
1825
1826 ;; record completion in BIOS task complete flag
1827 push ax
1828 push ds
1829 mov ax, 40h
1830 mov ds, ax
1831 mov byte ptr ds:[8Eh], 0FFh
1832 call eoi_both_pics
1833 pop ds
1834 pop ax
1835 iret
1836
1837int76_handler endp
1838
1839
1840;;
1841;; IRQ 8 handler (RTC)
1842;;
1843int70_handler:
1844 push es
1845 push ds
1846 DO_pusha
1847 C_SETUP
1848 call _int70_function
1849 DO_popa
1850 pop ds
1851 pop es
1852 iret
1853
1854
1855
1856if VBOX_BIOS_CPU lt 80386
1857;
1858; We're tight on space down below in the int08_handler, so put
1859; the 16-bit rollover code here.
1860;
1861int08_maybe_rollover:
1862 ja int08_rollover
1863 cmp ax, 00B0h
1864 jb int08_rollover_store
1865 ;; there has been a midnight rollover
1866int08_rollover:
1867 xor dx, dx
1868 xor ax, ax
1869
1870 inc byte ptr ds:[70h] ; increment rollover flag
1871int08_rollover_store:
1872 jmp int08_store_ticks
1873endif
1874
1875
1876;; --------------------------------------------------------
1877;; 8x8 font (first 128 characters)
1878;; --------------------------------------------------------
1879 BIOSORG 0FA6Eh, 0FA6Ch
1880include font8x8.inc
1881
1882
1883;; --------------------------------------------------------
1884;; INT 1Ah handler - Time of the day + PCI BIOS
1885;; --------------------------------------------------------
1886 BIOSORG_CHECK 0FE6Eh ; fixed wrt preceding table
1887int1a_handler:
1888if VBOX_BIOS_CPU ge 80386
1889 cmp ah, 0B1h
1890 jne int1a_normal
1891
1892 push es
1893 push ds
1894 C_SETUP
1895 .386
1896 pushad
1897 call _pci16_function
1898 popad
1899 .286
1900 pop ds
1901 pop es
1902 iret
1903endif
1904
1905int1a_normal:
1906 push es
1907 push ds
1908 DO_pusha
1909 C_SETUP
1910int1a_callfunction:
1911 call _int1a_function
1912 DO_popa
1913 pop ds
1914 pop es
1915 iret
1916
1917
1918;; --------------------------------------------------------
1919;; Timer tick - IRQ 0 handler
1920;; --------------------------------------------------------
1921 BIOSORG 0FEA5h, 0FEA3h
1922int08_handler:
1923if VBOX_BIOS_CPU ge 80386
1924 .386
1925 sti
1926 push eax
1927else
1928 sti
1929 push ax
1930endif
1931 push ds
1932 push dx
1933 mov ax, 40h
1934 mov ds, ax
1935
1936if VBOX_BIOS_CPU ge 80386
1937 mov eax, ds:[6Ch] ; get ticks dword
1938 inc eax
1939else
1940 mov ax, ds:[6Ch] ; get ticks dword
1941 mov dx, ds:[6Ch+2]
1942 inc ax ; inc+jz+inc saves two bytes over add+adc.
1943 jnz int08_compare
1944 inc dx
1945int08_compare:
1946endif
1947
1948 ;; compare eax to one day's worth of ticks (at 18.2 Hz)
1949if VBOX_BIOS_CPU ge 80386
1950 cmp eax, 1800B0h
1951 jb int08_store_ticks
1952else
1953 cmp dx, 18h
1954 jb int08_store_ticks
1955 jmp int08_maybe_rollover
1956endif
1957
1958if VBOX_BIOS_CPU ge 80386
1959 ;; there has been a midnight rollover
1960 xor eax, eax
1961 inc byte ptr ds:[70h] ; increment rollover flag
1962
1963int08_store_ticks:
1964 mov ds:[6Ch], eax
1965else
1966int08_store_ticks:
1967 mov ds:[6Ch], ax
1968 mov ds:[6Ch+2], dx
1969endif
1970
1971 ;; time to turn off floppy drive motor(s)?
1972 mov al, ds:[40h]
1973 or al, al
1974 jz int08_floppy_off
1975 dec al
1976 mov ds:[40h], al
1977 jnz int08_floppy_off
1978 ;; turn motor(s) off
1979 mov dx, 03F2h
1980 in al, dx
1981 and al, 0CFh
1982 out dx, al
1983int08_floppy_off:
1984
1985 int 1Ch ; call the user timer handler
1986
1987 cli
1988 call eoi_master_pic
1989 pop dx
1990 pop ds
1991if VBOX_BIOS_CPU ge 80386
1992 pop eax
1993 .286
1994else
1995 pop ax
1996endif
1997 iret
1998
1999
2000;; --------------------------------------------------------
2001;; Initial interrupt vector offsets for POST
2002;; --------------------------------------------------------
2003 BIOSORG 0FEF3h, 0FEF1h
2004vector_table:
2005
2006
2007
2008;; --------------------------------------------------------
2009;; BIOS copyright string
2010;; --------------------------------------------------------
2011 BIOSORG 0FF00h, 0FEFEh
2012bios_string:
2013 db BIOS_COPYRIGHT
2014
2015
2016;; --------------------------------------------------------
2017;; IRET - default interrupt handler
2018;; --------------------------------------------------------
2019 BIOSORG 0FF53h, 0FF51h
2020
2021dummy_iret:
2022 iret
2023
2024
2025;; --------------------------------------------------------
2026;; INT 05h - Print Screen service
2027;; --------------------------------------------------------
2028 BIOSORG_CHECK 0FF54h ; fixed wrt preceding
2029int05_handler:
2030 ;; Not implemented
2031 iret
2032
2033include smidmi.inc
2034
2035;; --------------------------------------------------------
2036;; Processor reset entry point
2037;; --------------------------------------------------------
2038 BIOSORG 0FFF0h, 0FFEEh
2039cpu_reset:
2040 ;; This is where the CPU starts executing after a reset
2041 jmp far ptr post
2042
2043 ;; BIOS build date
2044 db BIOS_BUILD_DATE
2045 db 0 ; padding
2046 ;; System model ID
2047 db SYS_MODEL_ID
2048 ;; Checksum byte
2049 db 0FFh
2050
2051
2052BIOSSEG ends
2053
2054 end
2055
Note: See TracBrowser for help on using the repository browser.

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