1 | /** @file
|
---|
2 | * BIOS POST routines. Used only during initialization.
|
---|
3 | */
|
---|
4 |
|
---|
5 | /*
|
---|
6 | * Copyright (C) 2004-2014 Oracle Corporation
|
---|
7 | *
|
---|
8 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
9 | * available from http://www.virtualbox.org. This file is free software;
|
---|
10 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
11 | * General Public License (GPL) as published by the Free Software
|
---|
12 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
13 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
14 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
15 | */
|
---|
16 |
|
---|
17 | #include <stdint.h>
|
---|
18 | #include <string.h>
|
---|
19 | #include "biosint.h"
|
---|
20 | #include "inlines.h"
|
---|
21 |
|
---|
22 | #if DEBUG_POST
|
---|
23 | # define DPRINT(...) BX_DEBUG(__VA_ARGS__)
|
---|
24 | #else
|
---|
25 | # define DPRINT(...)
|
---|
26 | #endif
|
---|
27 |
|
---|
28 | /* In general, checksumming ROMs in a VM just wastes time. */
|
---|
29 | //#define CHECKSUM_ROMS
|
---|
30 |
|
---|
31 | /* The format of a ROM is as follows:
|
---|
32 | *
|
---|
33 | * ------------------------------
|
---|
34 | * 0 | AA55h signature (word) |
|
---|
35 | * ------------------------------
|
---|
36 | * 2 | Size in 512B blocks (byte) |
|
---|
37 | * ------------------------------
|
---|
38 | * 3 | Start of executable code |
|
---|
39 | * | ....... |
|
---|
40 | * end | |
|
---|
41 | * ------------------------------
|
---|
42 | */
|
---|
43 |
|
---|
44 | typedef struct rom_hdr_tag {
|
---|
45 | uint16_t signature;
|
---|
46 | uint8_t num_blks;
|
---|
47 | uint8_t code;
|
---|
48 | } rom_hdr;
|
---|
49 |
|
---|
50 |
|
---|
51 | /* Calculate the checksum of a ROM. Note that the ROM might be
|
---|
52 | * larger than 64K.
|
---|
53 | */
|
---|
54 | static inline uint8_t rom_checksum(uint8_t __far *rom, uint8_t blocks)
|
---|
55 | {
|
---|
56 | uint8_t sum = 0;
|
---|
57 |
|
---|
58 | #ifdef CHECKSUM_ROMS
|
---|
59 | while (blocks--) {
|
---|
60 | int i;
|
---|
61 |
|
---|
62 | for (i = 0; i < 512; ++i)
|
---|
63 | sum += rom[i];
|
---|
64 | /* Add 512 bytes (32 paragraphs) to segment. */
|
---|
65 | rom = MK_FP(FP_SEG(rom) + (512 >> 4), 0);
|
---|
66 | }
|
---|
67 | #endif
|
---|
68 | return sum;
|
---|
69 | }
|
---|
70 |
|
---|
71 | /* Scan for ROMs in the given range and execute their POST code. */
|
---|
72 | void rom_scan(uint16_t start_seg, uint16_t end_seg)
|
---|
73 | {
|
---|
74 | rom_hdr __far *rom;
|
---|
75 | uint8_t rom_blks;
|
---|
76 |
|
---|
77 | DPRINT("Scanning for ROMs in %04X-%04X range\n", start_seg, end_seg);
|
---|
78 |
|
---|
79 | while (start_seg < end_seg) {
|
---|
80 | rom = MK_FP(start_seg, 0);
|
---|
81 | /* Check for the ROM signature. */
|
---|
82 | if (rom->signature == 0xAA55) {
|
---|
83 | DPRINT("Found ROM at segment %04X\n", start_seg);
|
---|
84 | if (!rom_checksum((void __far *)rom, rom->num_blks)) {
|
---|
85 | void (__far * rom_init)(void);
|
---|
86 |
|
---|
87 | /* Checksum good, initialize ROM. */
|
---|
88 | rom_init = (void __far *)&rom->code;
|
---|
89 | rom_init();
|
---|
90 | int_disable();
|
---|
91 | DPRINT("ROM initialized\n");
|
---|
92 |
|
---|
93 | /* Continue scanning past the end of this ROM. */
|
---|
94 | rom_blks = (rom->num_blks + 3) & ~3; /* 4 blocks = 2K */
|
---|
95 | start_seg += rom_blks / 4;
|
---|
96 | }
|
---|
97 | } else {
|
---|
98 | /* Scanning is done in 2K steps. */
|
---|
99 | start_seg += 2048 >> 4;
|
---|
100 | }
|
---|
101 | }
|
---|
102 | outb_cmos(0x12, 0x20);
|
---|
103 | }
|
---|