VirtualBox

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

Last change on this file was 100658, checked in by vboxsync, 10 months ago

BIOS: Reworked BIOS build to have a common core and add 286/386 specific modules (see bugref:6549).

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

© 2023 Oracle
ContactPrivacy policyTerms of Use