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, 17 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
RevLine 
[69300]1; $Id: orgs.asm 98103 2023-01-17 14:15:46Z 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 _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
[60579]152ifdef VBOX_WITH_AHCI
[67065]153extrn _ahci_init:near
[60579]154endif
[60610]155if VBOX_BIOS_CPU ge 80286
[67065]156extrn _int15_blkmove:near
[60610]157endif
[61054]158if VBOX_BIOS_CPU ge 80386
[75229]159extrn _int15_function32:near
[67065]160extrn _apic_setup:near
[61054]161endif
[38699]162
163
164;; Symbols referenced from C code
[67065]165public _diskette_param_table
166public _pmode_IDT
167public _rmode_IDT
168public post
169public eoi_both_pics
170public rtc_post
[38699]171
172;; Additional publics for easier disassembly and debugging
[41084]173ifndef DEBUG
[67065]174 DEBUG equ 1
[41084]175endif
[67065]176ifdef DEBUG
[38699]177
[67065]178public int08_handler
179public int0e_handler
180public int11_handler
181public int12_handler
182public int13_handler
183public int13_relocated
[60441]184if VBOX_BIOS_CPU eq 8086
[67065]185public jmp_call_ret_int13_out
[60441]186endif
[67065]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
[38699]222
223endif
224
[75233]225;; Keyboard related constants
226KBDC_DISABLE EQU 0ADh
227KBDC_ENABLE EQU 0AEh
228KBC_CMD EQU 64h
229KBC_DATA EQU 60h
230
231
[38699]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
[60422]237SET_DEFAULT_CPU_286
[38699]238
[67065]239BIOSSEG segment 'CODE'
240 assume cs:BIOSSEG
[38699]241
242;;
[51059]243;; Start of fixed code - eoi_jmp_post is kept near here to allow short jumps.
[38699]244;;
[67065]245 BIOSORG 0E030h, 0E02Eh
[51061]246eoi_both_pics:
[67065]247 mov al, PIC_CMD_EOI
248 out PIC_SLAVE, al
[38699]249eoi_master_pic:
[67065]250 mov al, PIC_CMD_EOI
251 out PIC_MASTER, al
252 ret
[38699]253
[67065]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
[44107]258
[67065]259 mov [bx], ax
260 mov [bx+2], dx
261 add bx, 4
262 loop set_int_vects
263 ret
[44107]264
[67065]265set_int_vects endp
[44107]266
[51059]267eoi_jmp_post:
[75233]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
[60402]275no_eoi_jmp_post:
[75233]276 mov ax, 40h
[67065]277 mov ds, ax
[75233]278 jmp dword ptr ds:[67h]
[51059]279
[67065]280seg_40_value: dw 40h ;; Replaces a push 40; pop ds.
[60441]281
[38699]282;; --------------------------------------------------------
283;; POST entry point
284;; --------------------------------------------------------
[67065]285 BIOSORG 0E05Bh, 0E059h
[38699]286post:
[67065]287 cli
[44107]288
[60422]289if VBOX_BIOS_CPU ge 80286
[67065]290 ;; Check if in protected (V86) mode. If so, the CPU needs
291 ;; to be reset.
[60422]292 .286p
[67065]293 smsw ax
294 test ax, 1
295 jz in_real_mode
296 SET_DEFAULT_CPU_286
[60441]297else
[67065]298 jmp in_real_mode
[60422]299endif
[44107]300
[67065]301 ;; Reset processor to get out of protected mode. Use system
302 ;; port instead of KBC.
[51059]303reset_sys:
[67065]304 mov al, 1
305 out 92h, al
306 jmp $ ; not strictly necessary in a VM
[69300]307
308
[44107]309in_real_mode:
[67065]310 ;; read the CMOS shutdown status
311 mov al, 0Fh
312 out CMOS_ADDR, al
313 in al, CMOS_DATA
[38699]314
[67065]315 ;; save status
316 xchg ah, al
[38699]317
[67065]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
[51059]323
[67065]324 ;; Warm boot, check the shutdown byte.
325 mov al, ah
326 or al, al
327 jnz cont_post
[51059]328
[67065]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.
[67490]333 mov ds, cs:[seg_40_value]
[67065]334 cmp word ptr ds:[72h], 1234h
335 jnz reset_sys ; trigger system reset
[51059]336
337cont_post:
[67065]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
[38699]343
[67065]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
[69300]351
[67065]352 xor al, al
[48446]353
[67065]354 ;; reset the DMA controllers
355 out 00Dh, al
356 out 0DAh, al
[48446]357
[67065]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
[48446]363
364check_shutdown:
[67065]365 ;; examine the shutdown status code
366 mov al, ah
367 cmp al, 0
368 jz normal_post
[48446]369
[67065]370 cmp al, 0Dh
371 jae normal_post
372 cmp al, 9
373 jne check_next_std
374 jmp return_blkmove
[69300]375check_next_std:
[38699]376
[75233]377 mov sp, 400h
[67065]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
[38699]384
[67065]385 ;; any other shutdown status values are ignored
386 ;; OpenSolaris sets the status to 0Ah in some cases?
387 jmp normal_post
[38699]388
389normal_post:
[67065]390 ;; shutdown code 0: normal startup
[44107]391
[67065]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
[38699]401
[67065]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
[38699]413
[67065]414 ;; clear the remaining base memory except for the top
415 ;; of the EBDA (the MP table is planted there)
416 xor bx, bx
[38699]417memory_zero_loop:
[67065]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
[38699]426memory_cleared:
[67065]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
[38699]432
433
[67065]434 C_SETUP
435 call _log_bios_start
[38699]436
[60422]437if VBOX_BIOS_CPU ge 80386
[67065]438 call pmode_setup
[60422]439endif
[38699]440
[67065]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
[38699]448
[67065]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
[69300]455
[67065]456 ;; base memory in K to 40:13
[84901]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
[67065]465 mov ds:[413h], ax
[38699]466
[67065]467 ;; manufacturing test at 40:12
468 ;; zeroed out above
[38699]469
[67065]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
[38699]480
[67065]481 call ebda_post
[38699]482
[67065]483 ;; Initialize PCI devices. This can and should be done early.
[60433]484if VBOX_BIOS_CPU ge 80386 ; (Impossible to do on 16-bit CPUs.)
[67065]485 call pcibios_init_iomem_bases
486 call pcibios_init_irqs
[60422]487endif
[67065]488 SET_INT_VECTOR 1Ah, BIOSSEG, int1a_handler
[50160]489
[67065]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
[38699]497
[67065]498 ;; video setup - must be done before POSTing VGA ROM
499 SET_INT_VECTOR 10h, BIOSSEG, int10_handler
[50160]500
[67065]501 ;; keyboard setup
502 SET_INT_VECTOR 09h, BIOSSEG, int09_handler
503 SET_INT_VECTOR 16h, BIOSSEG, int16_handler
[38699]504
[67065]505 xor ax, ax
506 mov ds, ax
507 mov al, 10h
508 mov ds:[496h], al ; keyboard status flags 3
[38699]509
[67065]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
[38699]516
[67065]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
[51000]522
[67065]523 push ds
524 C_SETUP
[50160]525
[67065]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_
[50160]531
[67065]532 ;; Initialize the keyboard
533 call _keyboard_init
534 pop ds
[38699]535
[67065]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
[38699]551
[67065]552 ;; Serial setup
[67888]553 SET_INT_VECTOR 0Bh, BIOSSEG, dummy_isr ; IRQ 3
554 SET_INT_VECTOR 0Ch, BIOSSEG, dummy_isr ; IRQ 4
[67065]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
[38699]571
[67065]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
[38699]577
[67065]578 jmp norm_post_cont
[38699]579
[42809]580
[38699]581;; --------------------------------------------------------
582;; NMI handler
583;; --------------------------------------------------------
[67065]584 BIOSORG 0E2C3h, 0E2C1h
[38699]585nmi:
[67065]586 C_SETUP
587 call _nmi_handler_msg
588 iret
[38699]589
590int75_handler:
[67065]591 out 0F0h, al ; clear IRQ13
592 call eoi_both_pics
593 int 2 ; emulate legacy NMI
594 iret
[38699]595
596
[67065]597hard_drive_post proc near
[38699]598
[67065]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
[69025]612 ;; The ATA init code sets up INT 41h/46h FDPT pointers
[67065]613 ret
[38699]614
[67065]615hard_drive_post endp
[38699]616
617
[48446]618norm_post_cont:
[67065]619 ;; PS/2 mouse setup
620 SET_INT_VECTOR 74h, BIOSSEG, int74_handler
[51059]621
[67065]622 ;; IRQ 13h (FPU exception) setup
623 SET_INT_VECTOR 75h, BIOSSEG, int75_handler
[51059]624
[67065]625 call init_pic
[51059]626
[67065]627 C_SETUP
[61054]628
629if VBOX_BIOS_CPU ge 80386
[67065]630 ;; Set up local APIC
631 .386
632 pushad
633 call _apic_setup
634 popad
635 SET_DEFAULT_CPU_286
[61054]636endif
637
[67065]638 ;; ATA/ATAPI driver setup
639 call _ata_init
640 call _ata_detect
[48446]641
642ifdef VBOX_WITH_AHCI
[67065]643 ; AHCI driver setup
[68611]644 ;; TODO: AHCI initialization needs timer, but enabling
645 ;; interrupts elsewhere may be risky. Just do it around
646 ;; the AHCI init.
647 sti
[67065]648 call _ahci_init
[68611]649 cli
[48446]650endif
651
652ifdef VBOX_WITH_SCSI
[67065]653 ; SCSI driver setup
654 call _scsi_init
[48446]655endif
656
[67065]657 ;; floppy setup
658 call floppy_post
[48446]659
[67065]660 ;; hard drive setup
661 call hard_drive_post
[48446]662
[67065]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_
[69300]668
[67115]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
[67065]681 call _print_bios_banner
[69300]682
[67065]683 ;; El Torito floppy/hard disk emulation
684 call _cdemu_init
[48446]685
[67065]686 ; TODO: what's the point of enabling interrupts here??
687 sti ; enable interrupts
688 int 19h
689 ;; does not return here
690 sti
[48446]691wait_forever:
[67065]692 hlt
693 jmp wait_forever
694 cli
695 hlt
[48446]696
[69300]697
[48446]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:
[67065]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
[48446]730
[60422]731
[38699]732;; --------------------------------------------------------
733;; INT 13h handler - Disk services
734;; --------------------------------------------------------
[67065]735 BIOSORG 0E3FEh, 0E3FCh
[38699]736
737int13_handler:
[67065]738 jmp int13_relocated
[38699]739
740
[95050]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
[95052]749 res_3 db ?
750 res_4 db ?
751 res_5 db ?
[95050]752 lzone dw ? ; Landing zone cylinder
753 spt db ? ; Sectors per track
[95052]754 res_6 db ?
[95050]755fd_entry ends
756
[38699]757;; --------------------------------------------------------
758;; Fixed Disk Parameter Table
759;; --------------------------------------------------------
[67065]760 BIOSORG_CHECK 0E401h ; fixed wrt preceding
[38699]761
762rom_fdpt:
[95050]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
[38699]773
[95050]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
[38699]789;; --------------------------------------------------------
790;; INT 19h handler - Boot load service
791;; --------------------------------------------------------
[67065]792 BIOSORG 0E6F2h, 0E6F0h
[38699]793
794int19_handler:
[67065]795 jmp int19_relocated
[38699]796
797
798
799;; --------------------------------------------------------
800;; System BIOS Configuration Table
801;; --------------------------------------------------------
[67065]802 BIOSORG_CHECK 0E6F5h ; fixed wrt preceding
[38699]803; must match BIOS_CONFIG_TABLE
804bios_cfg_table:
[67065]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)
[38699]818ifdef BX_CALL_INT15_4F
[67065]819 db 74h; or USE_EBDA
[38699]820else
[67065]821 db 64h; or USE_EBDA
[38699]822endif
[67065]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
[38699]855
856
857;; --------------------------------------------------------
858;; Baud Rate Generator Table
859;; --------------------------------------------------------
[67065]860 BIOSORG 0E729h, 0E727h
[38699]861
862
863;; --------------------------------------------------------
864;; INT 14h handler - Serial Communication Service
865;; --------------------------------------------------------
[67065]866 BIOSORG 0E739h, 0E737h
[38699]867int14_handler:
[67065]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
[38699]877
878
879
880;;
881;; Handler for unexpected hardware interrupts
882;;
883dummy_isr:
[67065]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
[38699]893
894
[67065]895init_pic proc near
[38699]896
[67065]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
[38699]916
[67065]917init_pic endp
[38699]918
[67065]919ebda_post proc near
[38699]920
[67065]921 SET_INT_VECTOR 0Dh, BIOSSEG, dummy_isr ; IRQ 5
922 SET_INT_VECTOR 0Fh, BIOSSEG, dummy_isr ; IRQ 7
[67888]923 SET_INT_VECTOR 72h, BIOSSEG, dummy_isr ; IRQ 10
924 SET_INT_VECTOR 73h, BIOSSEG, dummy_isr ; IRQ 11
[67065]925 SET_INT_VECTOR 77h, BIOSSEG, dummy_isr ; IRQ 15
[38699]926
[84901]927 ;; calculate EBDA segment
928 xor ax, ax
[67065]929 mov ds, ax
[84901]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
[67065]937 mov byte ptr ds:[0], EBDA_SIZE
[84901]938 ;; must reset DS to zero again
[67065]939 xor ax, ax
940 mov ds, ax
941 ret
[38699]942
[67065]943ebda_post endp
[38699]944
945
946
947;; --------------------------------------------------------
948;; INT 16h handler - Keyboard service
949;; --------------------------------------------------------
[67065]950 BIOSORG 0E82Eh, 0E82Ch
[38699]951int16_handler:
[67065]952 sti
[67785]953 ;; Flags are saved *after* enabling interrupts, and with
954 ;; implicitly cleared TF. Software may depend on that.
955 pushf
[67065]956 push es
957 push ds
958 DO_pusha
[38699]959
[67065]960 cmp ah, 0
961 je int16_F00
[38699]962
[67065]963 cmp ah, 10h
964 je int16_F00
[38699]965
[67065]966 C_SETUP
967 call _int16_function
968 DO_popa
969 pop ds
970 pop es
[67785]971 add sp, 2 ; Skip saved flags
[67065]972 iret
[38699]973
974int16_F00:
[67065]975 mov bx, 40h ; TODO: why 40h here and 0 elsewhere?
976 mov ds, bx
[38699]977int16_wait_for_key:
[67065]978 cli
979 mov bx, ds:[1Ah]
980 cmp bx, ds:[1Ch]
981 jne int16_key_found
982 sti
983 nop
[38699]984; TODO: review/enable?
985if 0
[67065]986 push ax
987 mov ax, 9002h
988 int 15h
989 pop ax
[38699]990endif
[67065]991 jmp int16_wait_for_key
[38699]992
993int16_key_found:
[67065]994 C_SETUP
995 call _int16_function
996 DO_popa
997 pop ds
998 pop es
[67785]999 add sp, 2 ; Skip saved flags
[40721]1000; TODO: review/enable? If so, flags should be restored here?
[38699]1001if 0
[67065]1002 push ax
1003 mov ax, 9202h
1004 int 15h
1005 pop ax
[38699]1006endif
[67065]1007 iret
[38699]1008
1009
[60422]1010if VBOX_BIOS_CPU ge 80386
[38699]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
[60422]1016endif
[38699]1017
1018
1019;; --------------------------------------------------------
1020;; INT 09h handler - Keyboard ISR (IRQ 1)
1021;; --------------------------------------------------------
[67065]1022 BIOSORG 0E987h, 0E985h
[38699]1023int09_handler:
[67065]1024 cli ; TODO: why? they're off already!
1025 push ax
1026 mov al, KBDC_DISABLE
1027 out KBC_CMD, al
[38699]1028
[67065]1029 in al, KBC_DATA
1030 push ds
1031 DO_pusha
1032 cld ; Before INT 15h (and any C code)
[38699]1033ifdef BX_CALL_INT15_4F
[67065]1034 mov ah, 4Fh
1035 stc
1036 int 15h ; keyboard intercept
1037 jnc int09_done
[38699]1038endif
[67065]1039 sti ; Only after calling INT 15h
[38699]1040
[67065]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
[38699]1048
1049int09_check_pause:
[67065]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
[38699]1056
1057int09_process_key:
[67065]1058 push es
1059 C_SETUP
1060 call _int09_function
1061 pop es
[38699]1062
1063int09_done:
[67065]1064 DO_popa
1065 pop ds
1066 cli
1067 call eoi_master_pic
[38699]1068
[67065]1069 mov al, KBDC_ENABLE
1070 out KBC_CMD, al
1071 pop ax
1072 iret
[38699]1073
1074
1075;; --------------------------------------------------------
[49286]1076;; INT 06h handler - Invalid Opcode Exception
1077;; --------------------------------------------------------
1078
1079int06_handler:
[67065]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
[49286]1089
1090;; --------------------------------------------------------
[38699]1091;; INT 13h handler - Diskette service
1092;; --------------------------------------------------------
[67065]1093 BIOSORG 0EC59h, 0EC57h
[38699]1094int13_diskette:
[67065]1095 jmp int13_noeltorito
[38699]1096
1097
1098
1099;; --------------------------------------------------------
1100;; INT 13h handler - Disk service
1101;; --------------------------------------------------------
1102int13_relocated:
[67065]1103 ;; check for an El-Torito function
1104 cmp ah, 4Ah
1105 jb int13_not_eltorito
[38699]1106
[67065]1107 cmp ah, 4Dh
1108 ja int13_not_eltorito
[38699]1109
[67065]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
[60441]1115if VBOX_BIOS_CPU eq 8086
1116jmp_call_ret_int13_out: dw offset int13_out
1117endif
[38699]1118
1119int13_not_eltorito:
[67065]1120 push es
1121 push ax ; TODO: better register save/restore
1122 push bx
1123 push cx
1124 push dx
[38699]1125
[67065]1126 ;; check if emulation is active
1127 call _cdemu_isactive
1128 cmp al, 0
1129 je int13_cdemu_inactive
[38699]1130
[67065]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
[38699]1137
[67065]1138 pop dx
1139 pop cx
1140 pop bx
1141 pop ax
1142 pop es
[38699]1143
[67065]1144 DO_pusha
1145 push es
1146 push ds
1147 C_SETUP ; TODO: setup environment only once?
[38699]1148
[67065]1149 DO_JMP_CALL_EX _int13_cdemu, int13_out, jmp_call_ret_int13_out ; ELDX not used
[38699]1150
1151int13_nocdemu:
[67065]1152 and dl, 0E0h ; mask to get device class
1153 cmp al, dl
1154 jne int13_cdemu_inactive
[38699]1155
[67065]1156 pop dx
1157 pop cx
1158 pop bx
1159 pop ax
1160 pop es
[38699]1161
[67065]1162 push ax
1163 push cx
1164 push dx
1165 push bx
[38699]1166
[67065]1167 dec dl ; real drive is dl - 1
1168 jmp int13_legacy
[38699]1169
1170int13_cdemu_inactive:
[67065]1171 pop dx
1172 pop cx
1173 pop bx
1174 pop ax
1175 pop es
[38699]1176
1177int13_noeltorito:
[67065]1178 push ax
1179 push cx
1180 push dx
1181 push bx
[38699]1182int13_legacy:
[67065]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?
[38699]1190
[67065]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
[38699]1195
[67065]1196 DO_JMP_CALL_EX _int13_diskette_function, int13_out, jmp_call_ret_int13_out
[38699]1197
1198int13_notfloppy:
[67065]1199 cmp dl, 0E0h
1200 jb int13_notcdrom
[38699]1201
[67065]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
[38699]1213
1214int13_notcdrom:
1215int13_disk:
[67065]1216 cmp ah,40h
1217 ja int13x
1218 call _int13_harddisk
1219 jmp int13_out
[38699]1220
1221int13x:
[67065]1222 call _int13_harddisk_ext
[38699]1223
1224int13_out:
[67065]1225 pop ds
1226 pop es
1227 DO_popa
1228 iret
[38699]1229
1230
1231
1232; parallel port detection: port in dx, index in bx, timeout in cl
[67065]1233detect_parport proc near
[38699]1234
[67065]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
[38699]1247
[67065]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
[38699]1254no_parport:
[67065]1255 ret
[38699]1256
[67065]1257detect_parport endp
[41084]1258
[38699]1259; setial port detection: port in dx, index in bx, timeout in cl
[67065]1260detect_serial proc near
[38699]1261
[67065]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
[38699]1269
[67065]1270 inc dx
1271 in al, dx
1272 cmp al, 2
1273 jne no_serial
[38699]1274
[67065]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
[38699]1285
1286no_serial:
[67065]1287 pop dx
1288 ret
[38699]1289
[67065]1290detect_serial endp
[38699]1291
1292
1293;;
1294;; POST: Floppy drive
1295;;
[67065]1296floppy_post proc near
[38699]1297
[67065]1298 xor ax, ax
1299 mov ds, ax
[38699]1300
[67065]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
[38699]1315
[67065]1316 mov ds:[48Bh], al ; configuration data
[38699]1317
[67065]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
[38699]1322
1323look_drive0:
[67065]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
[38699]1329
1330f0_missing:
[67065]1331 mov bl, 0 ; no drive 0
[38699]1332
1333look_drive1:
[67065]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
[38699]1338f1_missing:
[67065]1339 mov ds:[48Fh], bl ; store in BDA
[38699]1340
[67065]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
[38699]1349
[67065]1350 mov al, 2
1351 out 0Ah, al ; unmask DMA channel 2
[38699]1352
[67065]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
[38699]1356
[67065]1357 ret
[38699]1358
[67065]1359floppy_post endp
[38699]1360
1361
[67065]1362bcd_to_bin proc near
[38699]1363
[67065]1364 ;; in : AL in packed BCD format
1365 ;; out: AL in binary, AH always 0
[60441]1366if VBOX_BIOS_CPU ge 80186
[67065]1367 shl ax, 4
1368 shr al, 4
[60441]1369else
[67065]1370 push cx
1371 mov cl, 4
1372 shl ax, cl
1373 shr al, cl
1374 pop cx
[60441]1375endif
[67065]1376 aad
1377 ret
[38699]1378
[67065]1379bcd_to_bin endp
[38699]1380
[67065]1381rtc_post proc near
[38699]1382
[60422]1383if VBOX_BIOS_CPU lt 80386 ;; @todo fix loopy code below
[67065]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
[60422]1394
[67065]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
[60422]1407
[67065]1408 ;; get RTC hours
[60422]1409rtc_post_hours:
[67065]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
[60422]1421
1422rtc_pos_shift:
[67065]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
[60422]1430
1431else
[67065]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
[38699]1445
[67065]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
[38699]1458
[67065]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
[38699]1471
[67065]1472 mov ds:[46Ch], ecx ; timer tick count
1473 xor al, al ; TODO: redundant?
1474 mov ds:[470h], al ; rollover flag
1475 .286
[60422]1476endif
[67065]1477 ret
[38699]1478
[67065]1479rtc_post endp
[38699]1480
1481
1482
1483;; --------------------------------------------------------
1484;; INT 0Eh handler - Diskette IRQ 6 ISR
1485;; --------------------------------------------------------
[67065]1486 BIOSORG 0EF57h, 0EF55h
[38699]1487int0e_handler:
[67065]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
[38699]1498int0e_loop1:
[67065]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
[38699]1504
1505int0e_loop2:
[67065]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
[38699]1513
1514int0e_normal:
[67065]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
[38699]1525
1526
1527;; --------------------------------------------------------
1528;; Diskette Parameter Table
1529;; --------------------------------------------------------
[67065]1530 BIOSORG 0EFC7h, 0EFC5h
[38699]1531_diskette_param_table:
[67065]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
[38699]1543
1544
[38789]1545
1546;; --------------------------------------------------------
1547;; INT 17h handler - Printer service
1548;; --------------------------------------------------------
[67065]1549 BIOSORG_CHECK 0EFD2h ; fixed WRT preceding code
[43759]1550
[67065]1551 jmp int17_handler ; NT floppy boot workaround
1552 ; see @bugref{6481}
[38789]1553int17_handler:
[67065]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
[38789]1563
1564
[41084]1565
[38699]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:
[67065]1575 dw 0 ; limit 15:0
1576 dw 0 ; base 15:0
1577 dw 0Fh ; base 23:16
[38699]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:
[67065]1587 dw 3FFh ; limit 15:00
1588 dw 0 ; base 15:00
1589 dw 0 ; base 23:16
[38699]1590
1591
1592;;
1593;; INT 1Ch
1594;;
1595;; TODO: Why does this need a special handler?
[67065]1596int1c_handler: ;; user timer tick
1597 iret
[38699]1598
1599
1600
1601;; --------------------------------------------------------
1602;; INT 10h functions 0-Fh entry point
1603;; --------------------------------------------------------
[67065]1604 BIOSORG 0F045h, 0F043h
[38699]1605i10f0f_entry:
[67065]1606 iret
[38699]1607
1608
1609;; --------------------------------------------------------
1610;; INT 10h handler - MDA/CGA video
1611;; --------------------------------------------------------
[67065]1612 BIOSORG 0F065h, 0F063h
[38699]1613int10_handler:
[67065]1614 ;; do nothing - assumes VGA
1615 iret
[38699]1616
1617
1618;; --------------------------------------------------------
1619;; MDA/CGA Video Parameter Table (INT 1Dh)
1620;; --------------------------------------------------------
[67065]1621 BIOSORG 0F0A4h, 0F0A2h
[38699]1622mdacga_vpt:
1623
1624
1625;;
1626;; INT 18h - boot failure
1627;;
1628int18_handler:
[67065]1629 C_SETUP
1630 call _int18_panic_msg
1631 ;; TODO: handle failure better?
[84752]1632 sti
1633stay_here:
[67065]1634 hlt
[84752]1635 jmp stay_here
[38699]1636
1637;;
1638;; INT 19h - boot service - relocated
1639;;
1640int19_relocated:
[67065]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
[38699]1647
[67065]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
[38699]1656
[67065]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
[38699]1665
[67065]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
[38699]1674
[67065]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
[38699]1683
1684boot_setup:
1685; TODO: the drive should be in dl already??
[67065]1686;; mov dl, bl ; tell guest OS what boot drive is
[60422]1687if VBOX_BIOS_CPU lt 80386
[67065]1688 mov [bp], ax
1689 DO_shl ax, 4
1690 mov [bp+2], ax ; set ip
1691 mov ax, [bp]
[60422]1692else
[67065]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
[38699]1696
[67065]1697 shr eax, 4 ; get cs back
1698 .286
[60422]1699endif
[67065]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?
[38699]1707
[67065]1708 pop bp ; TODO: why'd we just zero it??
1709 iret ; beam me up scotty
[38699]1710
1711;; PCI BIOS
1712
1713include pcibios.inc
1714include pirq.inc
1715
[95053]1716if 0 ; Sample VPD table
[38699]1717
[95053]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
[38699]1733;; --------------------------------------------------------
1734;; INT 12h handler - Memory size
1735;; --------------------------------------------------------
[67065]1736 BIOSORG 0F841h, 0F83Fh
[38699]1737int12_handler:
[67065]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
[38699]1746
1747
1748;; --------------------------------------------------------
1749;; INT 11h handler - Equipment list service
1750;; --------------------------------------------------------
[67065]1751 BIOSORG_CHECK 0F84Dh ; fixed wrt preceding code
[38699]1752int11_handler:
[67065]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
[38699]1761
1762
1763;; --------------------------------------------------------
1764;; INT 15h handler - System services
1765;; --------------------------------------------------------
[67065]1766 BIOSORG_CHECK 0F859h ; fixed wrt preceding code
[38699]1767int15_handler:
[60610]1768
1769if VBOX_BIOS_CPU ge 80286
[67065]1770 cmp ah, 87h
1771 jne not_blkmove
[69300]1772
[67065]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
[60610]1785not_blkmove:
1786
1787endif
1788
[67065]1789 pushf
1790 push ds
1791 push es
1792 C_SETUP
[75229]1793if VBOX_BIOS_CPU ge 80386
1794 ;; int15_function32 exists in 386+ BIOS only, but INT 15h is
1795 ;; not 386-specific
[67065]1796 cmp ah, 0E8h
1797 je int15_handler32
1798 cmp ah, 0d0h
1799 je int15_handler32
[75229]1800endif
[67065]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
[38699]1806
[67065]1807 call _int15_function
[42770]1808int15_handler_popa_ret:
[67065]1809 DO_popa
[75229]1810if VBOX_BIOS_CPU ge 80386
[38699]1811int15_handler32_ret:
[75229]1812endif
[67065]1813 pop es
1814 pop ds
1815 popf
1816 jmp iret_modify_cf
[38699]1817
1818apm_call:
[67065]1819 call _apm_function
1820 jmp int15_handler_popa_ret
[38699]1821
1822int15_handler_mouse:
[67065]1823 call _int15_function_mouse
1824 jmp int15_handler_popa_ret
[38699]1825
[75229]1826if VBOX_BIOS_CPU ge 80386
[38699]1827int15_handler32:
[67065]1828 ;; need to save/restore 32-bit registers
1829 .386
1830 pushad
1831 call _int15_function32
1832 popad
1833 .286
[75229]1834 jmp int15_handler32_ret
[60422]1835endif
[38699]1836
1837;;
1838;; Perform an IRET but retain the current carry flag value
1839;;
1840iret_modify_cf:
[67065]1841 jc carry_set
1842 push bp
1843 mov bp, sp
1844 and byte ptr [bp + 6], 0FEh
[67694]1845 or word ptr [bp + 6], 0200h
[67065]1846 pop bp
1847 iret
[38699]1848carry_set:
[67065]1849 push bp
1850 mov bp, sp
[67694]1851 or word ptr [bp + 6], 0201h
[67065]1852 pop bp
1853 iret
[38699]1854
1855;;
1856;; INT 74h handler - PS/2 mouse (IRQ 12)
1857;;
[67065]1858int74_handler proc
[38699]1859
[67065]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
[38699]1874
[67065]1875 ;; make far call to EBDA:0022
[60441]1876if VBOX_BIOS_CPU ge 80186
[67065]1877 push 0
[60441]1878else
[67065]1879 xor ax, ax
1880 push ax
[60441]1881endif
[67065]1882 pop ds
1883 push ds:[40Eh]
1884 pop ds
1885 call far ptr ds:[22h]
[38699]1886int74_done:
[67065]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
[38699]1894
[67065]1895int74_handler endp
[38699]1896
[67065]1897int76_handler proc
[38699]1898
[67065]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
[38699]1909
[67065]1910int76_handler endp
[41084]1911
[60441]1912
1913;;
1914;; IRQ 8 handler (RTC)
1915;;
1916int70_handler:
[67065]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
[60441]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:
[67065]1935 ja int08_rollover
1936 cmp ax, 00B0h
1937 jb int08_rollover_store
1938 ;; there has been a midnight rollover
[60441]1939int08_rollover:
[67065]1940 xor dx, dx
1941 xor ax, ax
[60441]1942
[67065]1943 inc byte ptr ds:[70h] ; increment rollover flag
[60441]1944int08_rollover_store:
[67065]1945 jmp int08_store_ticks
[60441]1946endif
1947
1948
[38699]1949;; --------------------------------------------------------
1950;; 8x8 font (first 128 characters)
1951;; --------------------------------------------------------
[67065]1952 BIOSORG 0FA6Eh, 0FA6Ch
[38699]1953include font8x8.inc
1954
1955
1956;; --------------------------------------------------------
1957;; INT 1Ah handler - Time of the day + PCI BIOS
1958;; --------------------------------------------------------
[67065]1959 BIOSORG_CHECK 0FE6Eh ; fixed wrt preceding table
[38699]1960int1a_handler:
[60422]1961if VBOX_BIOS_CPU ge 80386
[67065]1962 cmp ah, 0B1h
1963 jne int1a_normal
[38699]1964
[67065]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
[60422]1976endif
[38699]1977
1978int1a_normal:
[67065]1979 push es
1980 push ds
1981 DO_pusha
1982 C_SETUP
[38699]1983int1a_callfunction:
[67065]1984 call _int1a_function
1985 DO_popa
1986 pop ds
1987 pop es
1988 iret
[38699]1989
1990
1991;; --------------------------------------------------------
1992;; Timer tick - IRQ 0 handler
1993;; --------------------------------------------------------
[67065]1994 BIOSORG 0FEA5h, 0FEA3h
[38699]1995int08_handler:
[60422]1996if VBOX_BIOS_CPU ge 80386
[67065]1997 .386
1998 sti
1999 push eax
[60422]2000else
[67065]2001 sti
2002 push ax
[60422]2003endif
[67065]2004 push ds
2005 push dx
2006 mov ax, 40h
2007 mov ds, ax
[38699]2008
[60422]2009if VBOX_BIOS_CPU ge 80386
[67065]2010 mov eax, ds:[6Ch] ; get ticks dword
2011 inc eax
[60422]2012else
[67065]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
[60433]2018int08_compare:
[60422]2019endif
[48195]2020
[67065]2021 ;; compare eax to one day's worth of ticks (at 18.2 Hz)
[60422]2022if VBOX_BIOS_CPU ge 80386
[67065]2023 cmp eax, 1800B0h
2024 jb int08_store_ticks
[60422]2025else
[67065]2026 cmp dx, 18h
2027 jb int08_store_ticks
2028 jmp int08_maybe_rollover
[60422]2029endif
[60433]2030
2031if VBOX_BIOS_CPU ge 80386
[67065]2032 ;; there has been a midnight rollover
2033 xor eax, eax
2034 inc byte ptr ds:[70h] ; increment rollover flag
[48195]2035
2036int08_store_ticks:
[67065]2037 mov ds:[6Ch], eax
[60422]2038else
[60433]2039int08_store_ticks:
[67065]2040 mov ds:[6Ch], ax
2041 mov ds:[6Ch+2], dx
[60422]2042endif
[48195]2043
[67065]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
[38699]2056int08_floppy_off:
2057
[67065]2058 int 1Ch ; call the user timer handler
[38699]2059
[67065]2060 cli
2061 call eoi_master_pic
2062 pop dx
2063 pop ds
[60422]2064if VBOX_BIOS_CPU ge 80386
[67065]2065 pop eax
2066 .286
[60422]2067else
[67065]2068 pop ax
[60422]2069endif
[67065]2070 iret
[38699]2071
2072
2073;; --------------------------------------------------------
2074;; Initial interrupt vector offsets for POST
2075;; --------------------------------------------------------
[67065]2076 BIOSORG 0FEF3h, 0FEF1h
[38699]2077vector_table:
2078
2079
2080
2081;; --------------------------------------------------------
2082;; BIOS copyright string
2083;; --------------------------------------------------------
[67065]2084 BIOSORG 0FF00h, 0FEFEh
[38699]2085bios_string:
[67065]2086 db BIOS_COPYRIGHT
[38699]2087
2088
2089;; --------------------------------------------------------
2090;; IRET - default interrupt handler
2091;; --------------------------------------------------------
[67065]2092 BIOSORG 0FF53h, 0FF51h
[38699]2093
2094dummy_iret:
[67065]2095 iret
[38699]2096
2097
2098;; --------------------------------------------------------
2099;; INT 05h - Print Screen service
2100;; --------------------------------------------------------
[67065]2101 BIOSORG_CHECK 0FF54h ; fixed wrt preceding
[38699]2102int05_handler:
[67065]2103 ;; Not implemented
2104 iret
[38699]2105
2106include smidmi.inc
2107
2108;; --------------------------------------------------------
2109;; Processor reset entry point
2110;; --------------------------------------------------------
[67065]2111 BIOSORG 0FFF0h, 0FFEEh
[38699]2112cpu_reset:
[67065]2113 ;; This is where the CPU starts executing after a reset
2114 jmp far ptr post
[38699]2115
[67065]2116 ;; BIOS build date
2117 db BIOS_BUILD_DATE
[95053]2118 db 0 ; null terminator
[67065]2119 ;; System model ID
2120 db SYS_MODEL_ID
2121 ;; Checksum byte
2122 db 0FFh
[38699]2123
2124
[67065]2125BIOSSEG ends
[38699]2126
[67065]2127 end
[43712]2128
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use