VirtualBox

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

Last change on this file since 67490 was 67490, checked in by vboxsync, 7 years ago

Whitespace.

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