VirtualBox

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

Last change on this file since 98103 was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use