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
RevLine 
[69300]1; $Id: orgs.asm 100658 2023-07-20 07:43:52Z vboxsync $
2;; @file
3; ???
4;
[38699]5
[69300]6;
[98103]7; Copyright (C) 2006-2023 Oracle and/or its affiliates.
[69300]8;
[96407]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
[69300]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
[43117]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
[60422]62
63include commondefs.inc
64
[84901]65EBDA_SIZE equ 1 ; 1K minimum -- other modules may add to it
[38699]66
[67065]67CMOS_ADDR equ 070h
68CMOS_DATA equ 071h
[38699]69
70
[67065]71PIC_CMD_EOI equ 020h
72PIC_MASTER equ 020h
73PIC_SLAVE equ 0A0h
[38699]74
[67065]75BIOS_FIX_BASE equ 0E000h
[38699]76
[60434]77if VBOX_BIOS_CPU ge 80286
[67065]78SYS_MODEL_ID equ 0FCh ; PC/AT
[95053]79SYS_SUBMODEL_ID equ 1
[60434]80else
[67065]81SYS_MODEL_ID equ 0FBh ; PC/XT
[95053]82SYS_SUBMODEL_ID equ 0
[60434]83endif
[67065]84BIOS_REVISION equ 1
[38699]85
[67065]86BIOS_BUILD_DATE equ '06/23/99'
87BIOS_COPYRIGHT equ 'Oracle VM VirtualBox BIOS'
[38699]88
[67065]89BX_ROMBIOS32 equ 0
90BX_CALL_INT15_4F equ 1
[38699]91
92;; Set a fixed BIOS location, with a marker for verification
[67065]93BIOSORG macro addr, addr_minus_two
[60433]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.
[67065]95 BIOSORG_CHECK_BEFORE addr_minus_two
96 org addr - BIOS_FIX_BASE - 2
97 db 'XM'
98 BIOSORG_CHECK addr
99 endm
[38699]100
101;; Set an interrupt vector (not very efficient if multiple vectors are
102;; programmed in one go)
[67065]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
[38699]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(!)
[67065]112C_SETUP macro
113 push cs
114 pop ds
115 cld
[38699]116endm
117
[60422]118
[38699]119;; External function in separate modules
[67065]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
[100658]144ifdef VBOX_WITH_SCSI
[67065]145extrn _scsi_init:near
[100658]146endif
[67065]147extrn _ata_detect:near
148extrn _cdemu_init:near
149extrn _keyboard_init:near
150extrn _print_bios_banner:near
151extrn rom_scan_:near
[60579]152ifdef VBOX_WITH_AHCI
[67065]153extrn _ahci_init:near
[60579]154endif
[60610]155if VBOX_BIOS_CPU ge 80286
[67065]156extrn _int15_blkmove:near
[100658]157extrn _inv_op_handler:near
[60610]158endif
[61054]159if VBOX_BIOS_CPU ge 80386
[75229]160extrn _int15_function32:near
[67065]161extrn _apic_setup:near
[100658]162extrn _pci16_function:near
[61054]163endif
[38699]164
165
166;; Symbols referenced from C code
[67065]167public _diskette_param_table
168public _pmode_IDT
169public _rmode_IDT
170public post
171public eoi_both_pics
172public rtc_post
[38699]173
174;; Additional publics for easier disassembly and debugging
[41084]175ifndef DEBUG
[67065]176 DEBUG equ 1
[41084]177endif
[67065]178ifdef DEBUG
[38699]179
[67065]180public int08_handler
181public int0e_handler
182public int11_handler
183public int12_handler
184public int13_handler
185public int13_relocated
[60441]186if VBOX_BIOS_CPU eq 8086
[67065]187public jmp_call_ret_int13_out
[60441]188endif
[67065]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
[38699]224
225endif
226
[75233]227;; Keyboard related constants
228KBDC_DISABLE EQU 0ADh
229KBDC_ENABLE EQU 0AEh
230KBC_CMD EQU 64h
231KBC_DATA EQU 60h
232
233
[38699]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
[60422]239SET_DEFAULT_CPU_286
[38699]240
[67065]241BIOSSEG segment 'CODE'
242 assume cs:BIOSSEG
[38699]243
244;;
[51059]245;; Start of fixed code - eoi_jmp_post is kept near here to allow short jumps.
[38699]246;;
[67065]247 BIOSORG 0E030h, 0E02Eh
[51061]248eoi_both_pics:
[67065]249 mov al, PIC_CMD_EOI
250 out PIC_SLAVE, al
[38699]251eoi_master_pic:
[67065]252 mov al, PIC_CMD_EOI
253 out PIC_MASTER, al
254 ret
[38699]255
[67065]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
[44107]260
[67065]261 mov [bx], ax
262 mov [bx+2], dx
263 add bx, 4
264 loop set_int_vects
265 ret
[44107]266
[67065]267set_int_vects endp
[44107]268
[51059]269eoi_jmp_post:
[75233]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
[60402]277no_eoi_jmp_post:
[75233]278 mov ax, 40h
[67065]279 mov ds, ax
[75233]280 jmp dword ptr ds:[67h]
[51059]281
[67065]282seg_40_value: dw 40h ;; Replaces a push 40; pop ds.
[60441]283
[38699]284;; --------------------------------------------------------
285;; POST entry point
286;; --------------------------------------------------------
[67065]287 BIOSORG 0E05Bh, 0E059h
[38699]288post:
[67065]289 cli
[44107]290
[60422]291if VBOX_BIOS_CPU ge 80286
[67065]292 ;; Check if in protected (V86) mode. If so, the CPU needs
293 ;; to be reset.
[60422]294 .286p
[67065]295 smsw ax
296 test ax, 1
297 jz in_real_mode
298 SET_DEFAULT_CPU_286
[60441]299else
[67065]300 jmp in_real_mode
[60422]301endif
[44107]302
[67065]303 ;; Reset processor to get out of protected mode. Use system
304 ;; port instead of KBC.
[51059]305reset_sys:
[67065]306 mov al, 1
307 out 92h, al
308 jmp $ ; not strictly necessary in a VM
[69300]309
310
[44107]311in_real_mode:
[67065]312 ;; read the CMOS shutdown status
313 mov al, 0Fh
314 out CMOS_ADDR, al
315 in al, CMOS_DATA
[38699]316
[67065]317 ;; save status
318 xchg ah, al
[38699]319
[67065]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
[51059]325
[67065]326 ;; Warm boot, check the shutdown byte.
327 mov al, ah
328 or al, al
329 jnz cont_post
[51059]330
[67065]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.
[67490]335 mov ds, cs:[seg_40_value]
[67065]336 cmp word ptr ds:[72h], 1234h
337 jnz reset_sys ; trigger system reset
[51059]338
339cont_post:
[67065]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
[38699]345
[67065]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
[69300]353
[67065]354 xor al, al
[48446]355
[67065]356 ;; reset the DMA controllers
357 out 00Dh, al
358 out 0DAh, al
[48446]359
[67065]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
[48446]365
366check_shutdown:
[67065]367 ;; examine the shutdown status code
368 mov al, ah
369 cmp al, 0
370 jz normal_post
[48446]371
[67065]372 cmp al, 0Dh
373 jae normal_post
374 cmp al, 9
375 jne check_next_std
376 jmp return_blkmove
[69300]377check_next_std:
[38699]378
[75233]379 mov sp, 400h
[67065]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
[38699]386
[67065]387 ;; any other shutdown status values are ignored
388 ;; OpenSolaris sets the status to 0Ah in some cases?
389 jmp normal_post
[38699]390
391normal_post:
[67065]392 ;; shutdown code 0: normal startup
[44107]393
[67065]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
[38699]403
[67065]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
[38699]415
[67065]416 ;; clear the remaining base memory except for the top
417 ;; of the EBDA (the MP table is planted there)
418 xor bx, bx
[38699]419memory_zero_loop:
[67065]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
[38699]428memory_cleared:
[67065]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
[38699]434
435
[67065]436 C_SETUP
437 call _log_bios_start
[38699]438
[60422]439if VBOX_BIOS_CPU ge 80386
[67065]440 call pmode_setup
[60422]441endif
[38699]442
[67065]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
[38699]450
[67065]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
[69300]457
[67065]458 ;; base memory in K to 40:13
[84901]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
[67065]467 mov ds:[413h], ax
[38699]468
[67065]469 ;; manufacturing test at 40:12
470 ;; zeroed out above
[38699]471
[67065]472 ;; set up various service vectors
473 ;; TODO: This should use the table at FEF3h instead
[100658]474if VBOX_BIOS_CPU ge 80286
[67065]475 SET_INT_VECTOR 06h, BIOSSEG, int06_handler
[100658]476endif
[67065]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
[38699]484
[67065]485 call ebda_post
[38699]486
[67065]487 ;; Initialize PCI devices. This can and should be done early.
[60433]488if VBOX_BIOS_CPU ge 80386 ; (Impossible to do on 16-bit CPUs.)
[67065]489 call pcibios_init_iomem_bases
490 call pcibios_init_irqs
[60422]491endif
[67065]492 SET_INT_VECTOR 1Ah, BIOSSEG, int1a_handler
[50160]493
[67065]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
[38699]501
[67065]502 ;; video setup - must be done before POSTing VGA ROM
503 SET_INT_VECTOR 10h, BIOSSEG, int10_handler
[50160]504
[67065]505 ;; keyboard setup
506 SET_INT_VECTOR 09h, BIOSSEG, int09_handler
507 SET_INT_VECTOR 16h, BIOSSEG, int16_handler
[38699]508
[67065]509 xor ax, ax
510 mov ds, ax
511 mov al, 10h
512 mov ds:[496h], al ; keyboard status flags 3
[38699]513
[67065]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
[38699]520
[67065]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
[51000]526
[67065]527 push ds
528 C_SETUP
[50160]529
[67065]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_
[50160]535
[67065]536 ;; Initialize the keyboard
537 call _keyboard_init
538 pop ds
[38699]539
[67065]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
[38699]555
[67065]556 ;; Serial setup
[67888]557 SET_INT_VECTOR 0Bh, BIOSSEG, dummy_isr ; IRQ 3
558 SET_INT_VECTOR 0Ch, BIOSSEG, dummy_isr ; IRQ 4
[67065]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
[38699]575
[67065]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
[38699]581
[67065]582 jmp norm_post_cont
[38699]583
[42809]584
[38699]585;; --------------------------------------------------------
586;; NMI handler
587;; --------------------------------------------------------
[67065]588 BIOSORG 0E2C3h, 0E2C1h
[38699]589nmi:
[67065]590 C_SETUP
591 call _nmi_handler_msg
592 iret
[38699]593
594int75_handler:
[67065]595 out 0F0h, al ; clear IRQ13
596 call eoi_both_pics
597 int 2 ; emulate legacy NMI
598 iret
[38699]599
600
[67065]601hard_drive_post proc near
[38699]602
[67065]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
[69025]616 ;; The ATA init code sets up INT 41h/46h FDPT pointers
[67065]617 ret
[38699]618
[67065]619hard_drive_post endp
[38699]620
621
[48446]622norm_post_cont:
[67065]623 ;; PS/2 mouse setup
624 SET_INT_VECTOR 74h, BIOSSEG, int74_handler
[51059]625
[67065]626 ;; IRQ 13h (FPU exception) setup
627 SET_INT_VECTOR 75h, BIOSSEG, int75_handler
[51059]628
[67065]629 call init_pic
[51059]630
[67065]631 C_SETUP
[61054]632
633if VBOX_BIOS_CPU ge 80386
[67065]634 ;; Set up local APIC
635 .386
636 pushad
637 call _apic_setup
638 popad
639 SET_DEFAULT_CPU_286
[61054]640endif
641
[67065]642 ;; ATA/ATAPI driver setup
643 call _ata_init
644 call _ata_detect
[48446]645
646ifdef VBOX_WITH_AHCI
[67065]647 ; AHCI driver setup
[68611]648 ;; TODO: AHCI initialization needs timer, but enabling
649 ;; interrupts elsewhere may be risky. Just do it around
650 ;; the AHCI init.
651 sti
[67065]652 call _ahci_init
[68611]653 cli
[48446]654endif
655
656ifdef VBOX_WITH_SCSI
[67065]657 ; SCSI driver setup
658 call _scsi_init
[48446]659endif
660
[67065]661 ;; floppy setup
662 call floppy_post
[48446]663
[67065]664 ;; hard drive setup
665 call hard_drive_post
[48446]666
[67065]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_
[69300]672
[67115]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
[67065]685 call _print_bios_banner
[69300]686
[67065]687 ;; El Torito floppy/hard disk emulation
688 call _cdemu_init
[48446]689
[67065]690 ; TODO: what's the point of enabling interrupts here??
691 sti ; enable interrupts
692 int 19h
693 ;; does not return here
694 sti
[48446]695wait_forever:
[67065]696 hlt
697 jmp wait_forever
698 cli
699 hlt
[48446]700
[69300]701
[48446]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:
[67065]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
[48446]734
[60422]735
[38699]736;; --------------------------------------------------------
737;; INT 13h handler - Disk services
738;; --------------------------------------------------------
[67065]739 BIOSORG 0E3FEh, 0E3FCh
[38699]740
741int13_handler:
[67065]742 jmp int13_relocated
[38699]743
744
[95050]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
[95052]753 res_3 db ?
754 res_4 db ?
755 res_5 db ?
[95050]756 lzone dw ? ; Landing zone cylinder
757 spt db ? ; Sectors per track
[95052]758 res_6 db ?
[95050]759fd_entry ends
760
[38699]761;; --------------------------------------------------------
762;; Fixed Disk Parameter Table
763;; --------------------------------------------------------
[67065]764 BIOSORG_CHECK 0E401h ; fixed wrt preceding
[38699]765
766rom_fdpt:
[95050]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
[38699]777
[95050]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
[38699]793;; --------------------------------------------------------
794;; INT 19h handler - Boot load service
795;; --------------------------------------------------------
[67065]796 BIOSORG 0E6F2h, 0E6F0h
[38699]797
798int19_handler:
[67065]799 jmp int19_relocated
[38699]800
801
802
803;; --------------------------------------------------------
804;; System BIOS Configuration Table
805;; --------------------------------------------------------
[67065]806 BIOSORG_CHECK 0E6F5h ; fixed wrt preceding
[38699]807; must match BIOS_CONFIG_TABLE
808bios_cfg_table:
[67065]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)
[38699]822ifdef BX_CALL_INT15_4F
[67065]823 db 74h; or USE_EBDA
[38699]824else
[67065]825 db 64h; or USE_EBDA
[38699]826endif
[67065]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
[38699]859
860
861;; --------------------------------------------------------
862;; Baud Rate Generator Table
863;; --------------------------------------------------------
[67065]864 BIOSORG 0E729h, 0E727h
[38699]865
866
867;; --------------------------------------------------------
868;; INT 14h handler - Serial Communication Service
869;; --------------------------------------------------------
[67065]870 BIOSORG 0E739h, 0E737h
[38699]871int14_handler:
[67065]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
[38699]881
882
883
884;;
885;; Handler for unexpected hardware interrupts
886;;
887dummy_isr:
[67065]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
[38699]897
898
[67065]899init_pic proc near
[38699]900
[67065]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
[38699]920
[67065]921init_pic endp
[38699]922
[67065]923ebda_post proc near
[38699]924
[67065]925 SET_INT_VECTOR 0Dh, BIOSSEG, dummy_isr ; IRQ 5
926 SET_INT_VECTOR 0Fh, BIOSSEG, dummy_isr ; IRQ 7
[67888]927 SET_INT_VECTOR 72h, BIOSSEG, dummy_isr ; IRQ 10
928 SET_INT_VECTOR 73h, BIOSSEG, dummy_isr ; IRQ 11
[67065]929 SET_INT_VECTOR 77h, BIOSSEG, dummy_isr ; IRQ 15
[38699]930
[84901]931 ;; calculate EBDA segment
932 xor ax, ax
[67065]933 mov ds, ax
[84901]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
[67065]941 mov byte ptr ds:[0], EBDA_SIZE
[84901]942 ;; must reset DS to zero again
[67065]943 xor ax, ax
944 mov ds, ax
945 ret
[38699]946
[67065]947ebda_post endp
[38699]948
949
950
951;; --------------------------------------------------------
952;; INT 16h handler - Keyboard service
953;; --------------------------------------------------------
[67065]954 BIOSORG 0E82Eh, 0E82Ch
[38699]955int16_handler:
[67065]956 sti
[67785]957 ;; Flags are saved *after* enabling interrupts, and with
958 ;; implicitly cleared TF. Software may depend on that.
959 pushf
[67065]960 push es
961 push ds
962 DO_pusha
[38699]963
[67065]964 cmp ah, 0
965 je int16_F00
[38699]966
[67065]967 cmp ah, 10h
968 je int16_F00
[38699]969
[67065]970 C_SETUP
971 call _int16_function
972 DO_popa
973 pop ds
974 pop es
[67785]975 add sp, 2 ; Skip saved flags
[67065]976 iret
[38699]977
978int16_F00:
[67065]979 mov bx, 40h ; TODO: why 40h here and 0 elsewhere?
980 mov ds, bx
[38699]981int16_wait_for_key:
[67065]982 cli
983 mov bx, ds:[1Ah]
984 cmp bx, ds:[1Ch]
985 jne int16_key_found
986 sti
987 nop
[38699]988; TODO: review/enable?
989if 0
[67065]990 push ax
991 mov ax, 9002h
992 int 15h
993 pop ax
[38699]994endif
[67065]995 jmp int16_wait_for_key
[38699]996
997int16_key_found:
[67065]998 C_SETUP
999 call _int16_function
1000 DO_popa
1001 pop ds
1002 pop es
[67785]1003 add sp, 2 ; Skip saved flags
[40721]1004; TODO: review/enable? If so, flags should be restored here?
[38699]1005if 0
[67065]1006 push ax
1007 mov ax, 9202h
1008 int 15h
1009 pop ax
[38699]1010endif
[67065]1011 iret
[38699]1012
1013
[60422]1014if VBOX_BIOS_CPU ge 80386
[38699]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
[60422]1020endif
[38699]1021
1022
1023;; --------------------------------------------------------
1024;; INT 09h handler - Keyboard ISR (IRQ 1)
1025;; --------------------------------------------------------
[67065]1026 BIOSORG 0E987h, 0E985h
[38699]1027int09_handler:
[67065]1028 cli ; TODO: why? they're off already!
1029 push ax
1030 mov al, KBDC_DISABLE
1031 out KBC_CMD, al
[38699]1032
[67065]1033 in al, KBC_DATA
1034 push ds
1035 DO_pusha
1036 cld ; Before INT 15h (and any C code)
[38699]1037ifdef BX_CALL_INT15_4F
[67065]1038 mov ah, 4Fh
1039 stc
1040 int 15h ; keyboard intercept
1041 jnc int09_done
[38699]1042endif
[67065]1043 sti ; Only after calling INT 15h
[38699]1044
[67065]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
[38699]1052
1053int09_check_pause:
[67065]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
[38699]1060
1061int09_process_key:
[67065]1062 push es
1063 C_SETUP
1064 call _int09_function
1065 pop es
[38699]1066
1067int09_done:
[67065]1068 DO_popa
1069 pop ds
1070 cli
1071 call eoi_master_pic
[38699]1072
[67065]1073 mov al, KBDC_ENABLE
1074 out KBC_CMD, al
1075 pop ax
1076 iret
[38699]1077
1078
[100658]1079if VBOX_BIOS_CPU ge 80286
1080
[38699]1081;; --------------------------------------------------------
[49286]1082;; INT 06h handler - Invalid Opcode Exception
1083;; --------------------------------------------------------
1084
1085int06_handler:
[67065]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
[49286]1095
[100658]1096endif
1097
[49286]1098;; --------------------------------------------------------
[38699]1099;; INT 13h handler - Diskette service
1100;; --------------------------------------------------------
[67065]1101 BIOSORG 0EC59h, 0EC57h
[38699]1102int13_diskette:
[67065]1103 jmp int13_noeltorito
[38699]1104
1105
1106
1107;; --------------------------------------------------------
1108;; INT 13h handler - Disk service
1109;; --------------------------------------------------------
1110int13_relocated:
[67065]1111 ;; check for an El-Torito function
1112 cmp ah, 4Ah
1113 jb int13_not_eltorito
[38699]1114
[67065]1115 cmp ah, 4Dh
1116 ja int13_not_eltorito
[38699]1117
[67065]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
[60441]1123if VBOX_BIOS_CPU eq 8086
1124jmp_call_ret_int13_out: dw offset int13_out
1125endif
[38699]1126
1127int13_not_eltorito:
[67065]1128 push es
1129 push ax ; TODO: better register save/restore
1130 push bx
1131 push cx
1132 push dx
[38699]1133
[67065]1134 ;; check if emulation is active
1135 call _cdemu_isactive
1136 cmp al, 0
1137 je int13_cdemu_inactive
[38699]1138
[67065]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
[38699]1145
[67065]1146 pop dx
1147 pop cx
1148 pop bx
1149 pop ax
1150 pop es
[38699]1151
[67065]1152 DO_pusha
1153 push es
1154 push ds
1155 C_SETUP ; TODO: setup environment only once?
[38699]1156
[67065]1157 DO_JMP_CALL_EX _int13_cdemu, int13_out, jmp_call_ret_int13_out ; ELDX not used
[38699]1158
1159int13_nocdemu:
[67065]1160 and dl, 0E0h ; mask to get device class
1161 cmp al, dl
1162 jne int13_cdemu_inactive
[38699]1163
[67065]1164 pop dx
1165 pop cx
1166 pop bx
1167 pop ax
1168 pop es
[38699]1169
[67065]1170 push ax
1171 push cx
1172 push dx
1173 push bx
[38699]1174
[67065]1175 dec dl ; real drive is dl - 1
1176 jmp int13_legacy
[38699]1177
1178int13_cdemu_inactive:
[67065]1179 pop dx
1180 pop cx
1181 pop bx
1182 pop ax
1183 pop es
[38699]1184
1185int13_noeltorito:
[67065]1186 push ax
1187 push cx
1188 push dx
1189 push bx
[38699]1190int13_legacy:
[67065]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?
[38699]1198
[67065]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
[38699]1203
[67065]1204 DO_JMP_CALL_EX _int13_diskette_function, int13_out, jmp_call_ret_int13_out
[38699]1205
1206int13_notfloppy:
[67065]1207 cmp dl, 0E0h
1208 jb int13_notcdrom
[38699]1209
[67065]1210 call _int13_cdrom
1211 jmp int13_out
[38699]1212
1213int13_notcdrom:
1214int13_disk:
[67065]1215 cmp ah,40h
1216 ja int13x
1217 call _int13_harddisk
1218 jmp int13_out
[38699]1219
1220int13x:
[67065]1221 call _int13_harddisk_ext
[38699]1222
1223int13_out:
[67065]1224 pop ds
1225 pop es
1226 DO_popa
1227 iret
[38699]1228
1229
1230
1231; parallel port detection: port in dx, index in bx, timeout in cl
[67065]1232detect_parport proc near
[38699]1233
[67065]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
[38699]1246
[67065]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
[38699]1253no_parport:
[67065]1254 ret
[38699]1255
[67065]1256detect_parport endp
[41084]1257
[38699]1258; setial port detection: port in dx, index in bx, timeout in cl
[67065]1259detect_serial proc near
[38699]1260
[67065]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
[38699]1268
[67065]1269 inc dx
1270 in al, dx
1271 cmp al, 2
1272 jne no_serial
[38699]1273
[67065]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
[38699]1284
1285no_serial:
[67065]1286 pop dx
1287 ret
[38699]1288
[67065]1289detect_serial endp
[38699]1290
1291
1292;;
1293;; POST: Floppy drive
1294;;
[67065]1295floppy_post proc near
[38699]1296
[67065]1297 xor ax, ax
1298 mov ds, ax
[38699]1299
[67065]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
[38699]1314
[67065]1315 mov ds:[48Bh], al ; configuration data
[38699]1316
[67065]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
[38699]1321
1322look_drive0:
[67065]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
[38699]1328
1329f0_missing:
[67065]1330 mov bl, 0 ; no drive 0
[38699]1331
1332look_drive1:
[67065]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
[38699]1337f1_missing:
[67065]1338 mov ds:[48Fh], bl ; store in BDA
[38699]1339
[67065]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
[38699]1348
[67065]1349 mov al, 2
1350 out 0Ah, al ; unmask DMA channel 2
[38699]1351
[67065]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
[38699]1355
[67065]1356 ret
[38699]1357
[67065]1358floppy_post endp
[38699]1359
1360
[67065]1361bcd_to_bin proc near
[38699]1362
[67065]1363 ;; in : AL in packed BCD format
1364 ;; out: AL in binary, AH always 0
[60441]1365if VBOX_BIOS_CPU ge 80186
[67065]1366 shl ax, 4
1367 shr al, 4
[60441]1368else
[67065]1369 push cx
1370 mov cl, 4
1371 shl ax, cl
1372 shr al, cl
1373 pop cx
[60441]1374endif
[67065]1375 aad
1376 ret
[38699]1377
[67065]1378bcd_to_bin endp
[38699]1379
[67065]1380rtc_post proc near
[38699]1381
[60422]1382if VBOX_BIOS_CPU lt 80386 ;; @todo fix loopy code below
[67065]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
[60422]1393
[67065]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
[60422]1406
[67065]1407 ;; get RTC hours
[60422]1408rtc_post_hours:
[67065]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
[60422]1420
1421rtc_pos_shift:
[67065]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
[60422]1429
1430else
[67065]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
[38699]1444
[67065]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
[38699]1457
[67065]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
[38699]1470
[67065]1471 mov ds:[46Ch], ecx ; timer tick count
1472 xor al, al ; TODO: redundant?
1473 mov ds:[470h], al ; rollover flag
1474 .286
[60422]1475endif
[67065]1476 ret
[38699]1477
[67065]1478rtc_post endp
[38699]1479
1480
1481
1482;; --------------------------------------------------------
1483;; INT 0Eh handler - Diskette IRQ 6 ISR
1484;; --------------------------------------------------------
[67065]1485 BIOSORG 0EF57h, 0EF55h
[38699]1486int0e_handler:
[67065]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
[38699]1497int0e_loop1:
[67065]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
[38699]1503
1504int0e_loop2:
[67065]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
[38699]1512
1513int0e_normal:
[67065]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
[38699]1524
1525
1526;; --------------------------------------------------------
1527;; Diskette Parameter Table
1528;; --------------------------------------------------------
[67065]1529 BIOSORG 0EFC7h, 0EFC5h
[38699]1530_diskette_param_table:
[67065]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
[38699]1542
1543
[38789]1544
1545;; --------------------------------------------------------
1546;; INT 17h handler - Printer service
1547;; --------------------------------------------------------
[67065]1548 BIOSORG_CHECK 0EFD2h ; fixed WRT preceding code
[43759]1549
[67065]1550 jmp int17_handler ; NT floppy boot workaround
1551 ; see @bugref{6481}
[38789]1552int17_handler:
[67065]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
[38789]1562
1563
[41084]1564
[38699]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:
[67065]1574 dw 0 ; limit 15:0
1575 dw 0 ; base 15:0
1576 dw 0Fh ; base 23:16
[38699]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:
[67065]1586 dw 3FFh ; limit 15:00
1587 dw 0 ; base 15:00
1588 dw 0 ; base 23:16
[38699]1589
1590
1591;;
1592;; INT 1Ch
1593;;
1594;; TODO: Why does this need a special handler?
[67065]1595int1c_handler: ;; user timer tick
1596 iret
[38699]1597
1598
1599
1600;; --------------------------------------------------------
1601;; INT 10h functions 0-Fh entry point
1602;; --------------------------------------------------------
[67065]1603 BIOSORG 0F045h, 0F043h
[38699]1604i10f0f_entry:
[67065]1605 iret
[38699]1606
1607
1608;; --------------------------------------------------------
1609;; INT 10h handler - MDA/CGA video
1610;; --------------------------------------------------------
[67065]1611 BIOSORG 0F065h, 0F063h
[38699]1612int10_handler:
[67065]1613 ;; do nothing - assumes VGA
1614 iret
[38699]1615
1616
1617;; --------------------------------------------------------
1618;; MDA/CGA Video Parameter Table (INT 1Dh)
1619;; --------------------------------------------------------
[67065]1620 BIOSORG 0F0A4h, 0F0A2h
[38699]1621mdacga_vpt:
1622
1623
1624;;
1625;; INT 18h - boot failure
1626;;
1627int18_handler:
[67065]1628 C_SETUP
1629 call _int18_panic_msg
1630 ;; TODO: handle failure better?
[84752]1631 sti
1632stay_here:
[67065]1633 hlt
[84752]1634 jmp stay_here
[38699]1635
1636;;
1637;; INT 19h - boot service - relocated
1638;;
1639int19_relocated:
[67065]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
[38699]1646
[67065]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
[38699]1655
[67065]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
[38699]1664
[67065]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
[38699]1673
[67065]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
[38699]1682
1683boot_setup:
1684; TODO: the drive should be in dl already??
[67065]1685;; mov dl, bl ; tell guest OS what boot drive is
[60422]1686if VBOX_BIOS_CPU lt 80386
[67065]1687 mov [bp], ax
1688 DO_shl ax, 4
1689 mov [bp+2], ax ; set ip
1690 mov ax, [bp]
[60422]1691else
[67065]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
[38699]1695
[67065]1696 shr eax, 4 ; get cs back
1697 .286
[60422]1698endif
[67065]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?
[38699]1706
[67065]1707 pop bp ; TODO: why'd we just zero it??
1708 iret ; beam me up scotty
[38699]1709
[100658]1710if VBOX_BIOS_CPU ge 80386
1711
[38699]1712;; PCI BIOS
1713
1714include pcibios.inc
1715include pirq.inc
1716
[100658]1717endif
1718
[95053]1719if 0 ; Sample VPD table
[38699]1720
[95053]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
[38699]1736;; --------------------------------------------------------
1737;; INT 12h handler - Memory size
1738;; --------------------------------------------------------
[67065]1739 BIOSORG 0F841h, 0F83Fh
[38699]1740int12_handler:
[67065]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
[38699]1749
1750
1751;; --------------------------------------------------------
1752;; INT 11h handler - Equipment list service
1753;; --------------------------------------------------------
[67065]1754 BIOSORG_CHECK 0F84Dh ; fixed wrt preceding code
[38699]1755int11_handler:
[67065]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
[38699]1764
1765
1766;; --------------------------------------------------------
1767;; INT 15h handler - System services
1768;; --------------------------------------------------------
[67065]1769 BIOSORG_CHECK 0F859h ; fixed wrt preceding code
[38699]1770int15_handler:
[60610]1771
1772if VBOX_BIOS_CPU ge 80286
[67065]1773 cmp ah, 87h
1774 jne not_blkmove
[69300]1775
[67065]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
[60610]1788not_blkmove:
1789
1790endif
1791
[67065]1792 pushf
1793 push ds
1794 push es
1795 C_SETUP
[75229]1796if VBOX_BIOS_CPU ge 80386
1797 ;; int15_function32 exists in 386+ BIOS only, but INT 15h is
1798 ;; not 386-specific
[67065]1799 cmp ah, 0E8h
1800 je int15_handler32
1801 cmp ah, 0d0h
1802 je int15_handler32
[75229]1803endif
[67065]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
[38699]1809
[67065]1810 call _int15_function
[42770]1811int15_handler_popa_ret:
[67065]1812 DO_popa
[75229]1813if VBOX_BIOS_CPU ge 80386
[38699]1814int15_handler32_ret:
[75229]1815endif
[67065]1816 pop es
1817 pop ds
1818 popf
1819 jmp iret_modify_cf
[38699]1820
1821apm_call:
[67065]1822 call _apm_function
1823 jmp int15_handler_popa_ret
[38699]1824
1825int15_handler_mouse:
[67065]1826 call _int15_function_mouse
1827 jmp int15_handler_popa_ret
[38699]1828
[75229]1829if VBOX_BIOS_CPU ge 80386
[38699]1830int15_handler32:
[67065]1831 ;; need to save/restore 32-bit registers
1832 .386
1833 pushad
1834 call _int15_function32
1835 popad
1836 .286
[75229]1837 jmp int15_handler32_ret
[60422]1838endif
[38699]1839
1840;;
1841;; Perform an IRET but retain the current carry flag value
1842;;
1843iret_modify_cf:
[67065]1844 jc carry_set
1845 push bp
1846 mov bp, sp
1847 and byte ptr [bp + 6], 0FEh
[67694]1848 or word ptr [bp + 6], 0200h
[67065]1849 pop bp
1850 iret
[38699]1851carry_set:
[67065]1852 push bp
1853 mov bp, sp
[67694]1854 or word ptr [bp + 6], 0201h
[67065]1855 pop bp
1856 iret
[38699]1857
1858;;
1859;; INT 74h handler - PS/2 mouse (IRQ 12)
1860;;
[67065]1861int74_handler proc
[38699]1862
[67065]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
[38699]1877
[67065]1878 ;; make far call to EBDA:0022
[60441]1879if VBOX_BIOS_CPU ge 80186
[67065]1880 push 0
[60441]1881else
[67065]1882 xor ax, ax
1883 push ax
[60441]1884endif
[67065]1885 pop ds
1886 push ds:[40Eh]
1887 pop ds
1888 call far ptr ds:[22h]
[38699]1889int74_done:
[67065]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
[38699]1897
[67065]1898int74_handler endp
[38699]1899
[67065]1900int76_handler proc
[38699]1901
[67065]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
[38699]1912
[67065]1913int76_handler endp
[41084]1914
[60441]1915
1916;;
1917;; IRQ 8 handler (RTC)
1918;;
1919int70_handler:
[67065]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
[60441]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:
[67065]1938 ja int08_rollover
1939 cmp ax, 00B0h
1940 jb int08_rollover_store
1941 ;; there has been a midnight rollover
[60441]1942int08_rollover:
[67065]1943 xor dx, dx
1944 xor ax, ax
[60441]1945
[67065]1946 inc byte ptr ds:[70h] ; increment rollover flag
[60441]1947int08_rollover_store:
[67065]1948 jmp int08_store_ticks
[60441]1949endif
1950
1951
[38699]1952;; --------------------------------------------------------
1953;; 8x8 font (first 128 characters)
1954;; --------------------------------------------------------
[67065]1955 BIOSORG 0FA6Eh, 0FA6Ch
[38699]1956include font8x8.inc
1957
1958
1959;; --------------------------------------------------------
1960;; INT 1Ah handler - Time of the day + PCI BIOS
1961;; --------------------------------------------------------
[67065]1962 BIOSORG_CHECK 0FE6Eh ; fixed wrt preceding table
[38699]1963int1a_handler:
[60422]1964if VBOX_BIOS_CPU ge 80386
[67065]1965 cmp ah, 0B1h
1966 jne int1a_normal
[38699]1967
[67065]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
[60422]1979endif
[38699]1980
1981int1a_normal:
[67065]1982 push es
1983 push ds
1984 DO_pusha
1985 C_SETUP
[38699]1986int1a_callfunction:
[67065]1987 call _int1a_function
1988 DO_popa
1989 pop ds
1990 pop es
1991 iret
[38699]1992
1993
1994;; --------------------------------------------------------
1995;; Timer tick - IRQ 0 handler
1996;; --------------------------------------------------------
[67065]1997 BIOSORG 0FEA5h, 0FEA3h
[38699]1998int08_handler:
[60422]1999if VBOX_BIOS_CPU ge 80386
[67065]2000 .386
2001 sti
2002 push eax
[60422]2003else
[67065]2004 sti
2005 push ax
[60422]2006endif
[67065]2007 push ds
2008 push dx
2009 mov ax, 40h
2010 mov ds, ax
[38699]2011
[60422]2012if VBOX_BIOS_CPU ge 80386
[67065]2013 mov eax, ds:[6Ch] ; get ticks dword
2014 inc eax
[60422]2015else
[67065]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
[60433]2021int08_compare:
[60422]2022endif
[48195]2023
[67065]2024 ;; compare eax to one day's worth of ticks (at 18.2 Hz)
[60422]2025if VBOX_BIOS_CPU ge 80386
[67065]2026 cmp eax, 1800B0h
2027 jb int08_store_ticks
[60422]2028else
[67065]2029 cmp dx, 18h
2030 jb int08_store_ticks
2031 jmp int08_maybe_rollover
[60422]2032endif
[60433]2033
2034if VBOX_BIOS_CPU ge 80386
[67065]2035 ;; there has been a midnight rollover
2036 xor eax, eax
2037 inc byte ptr ds:[70h] ; increment rollover flag
[48195]2038
2039int08_store_ticks:
[67065]2040 mov ds:[6Ch], eax
[60422]2041else
[60433]2042int08_store_ticks:
[67065]2043 mov ds:[6Ch], ax
2044 mov ds:[6Ch+2], dx
[60422]2045endif
[48195]2046
[67065]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
[38699]2059int08_floppy_off:
2060
[67065]2061 int 1Ch ; call the user timer handler
[38699]2062
[67065]2063 cli
2064 call eoi_master_pic
2065 pop dx
2066 pop ds
[60422]2067if VBOX_BIOS_CPU ge 80386
[67065]2068 pop eax
2069 .286
[60422]2070else
[67065]2071 pop ax
[60422]2072endif
[67065]2073 iret
[38699]2074
2075
2076;; --------------------------------------------------------
2077;; Initial interrupt vector offsets for POST
2078;; --------------------------------------------------------
[67065]2079 BIOSORG 0FEF3h, 0FEF1h
[38699]2080vector_table:
2081
2082
2083
2084;; --------------------------------------------------------
2085;; BIOS copyright string
2086;; --------------------------------------------------------
[67065]2087 BIOSORG 0FF00h, 0FEFEh
[38699]2088bios_string:
[67065]2089 db BIOS_COPYRIGHT
[38699]2090
2091
2092;; --------------------------------------------------------
2093;; IRET - default interrupt handler
2094;; --------------------------------------------------------
[67065]2095 BIOSORG 0FF53h, 0FF51h
[38699]2096
2097dummy_iret:
[67065]2098 iret
[38699]2099
2100
2101;; --------------------------------------------------------
2102;; INT 05h - Print Screen service
2103;; --------------------------------------------------------
[67065]2104 BIOSORG_CHECK 0FF54h ; fixed wrt preceding
[38699]2105int05_handler:
[67065]2106 ;; Not implemented
2107 iret
[38699]2108
2109include smidmi.inc
2110
2111;; --------------------------------------------------------
2112;; Processor reset entry point
2113;; --------------------------------------------------------
[67065]2114 BIOSORG 0FFF0h, 0FFEEh
[38699]2115cpu_reset:
[67065]2116 ;; This is where the CPU starts executing after a reset
2117 jmp far ptr post
[38699]2118
[67065]2119 ;; BIOS build date
2120 db BIOS_BUILD_DATE
[95053]2121 db 0 ; null terminator
[67065]2122 ;; System model ID
2123 db SYS_MODEL_ID
2124 ;; Checksum byte
2125 db 0FFh
[38699]2126
2127
[67065]2128BIOSSEG ends
[38699]2129
[67065]2130 end
[43712]2131
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use