VirtualBox

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

Last change on this file since 82176 was 81089, checked in by vboxsync, 5 years ago

Devices/BIOS: Skeleton of a VirtIO driver, just detects any device for now, bugref:9440

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