VirtualBox

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

Last change on this file since 84760 was 84752, checked in by vboxsync, 5 years ago

BIOS: On boot failure, call into INT 18h and report that to the host through the shutdown interface (see bugref:6549).

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

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