VirtualBox

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

Last change on this file since 75229 was 75229, checked in by vboxsync, 6 years ago

BIOS: Rearranged INT 15h to better separate 286 and 386+ functionality.

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

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