summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/PC/BIOS/bios.c
blob: 5d6c748b9e4e37844284762155023e0e4d00c7c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/* $Id: bios.c $ */
/** @file
 * PC BIOS - ???
 */

/*
 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * SPDX-License-Identifier: GPL-3.0-only
 * --------------------------------------------------------------------
 *
 * This code is based on:
 *
 *  ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
 *
 *  Copyright (C) 2002  MandrakeSoft S.A.
 *
 *    MandrakeSoft S.A.
 *    43, rue d'Aboukir
 *    75002 Paris - France
 *    http://www.linux-mandrake.com/
 *    http://www.mandrakesoft.com/
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 *
 */

/*
 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
 * a choice of LGPL license versions is made available with the language indicating
 * that LGPLv2 or any later version may be used, or where a choice of which version
 * of the LGPL is applied is otherwise unspecified.
 */


#include <stdint.h>
#include "inlines.h"
#include "biosint.h"
#include "VBox/bios.h"
#ifndef VBOX_VERSION_STRING
#include <VBox/version.h>
#endif

static  const char  bios_cvs_version_string[] = "VirtualBox " VBOX_VERSION_STRING;

uint8_t inb_cmos(uint8_t cmos_reg)
{
    uint8_t     cmos_port = 0x70;

    if (cmos_reg >= 0x80)
        cmos_port += 2;
    outb(cmos_port, cmos_reg);
    return inb(cmos_port + 1);
}

void outb_cmos(uint8_t cmos_reg, uint8_t val)
{
    uint8_t     cmos_port = 0x70;

    if (cmos_reg >= 0x80)
        cmos_port += 2;
    outb(cmos_port, cmos_reg);
    outb(cmos_port + 1, val);
}

/**
 * Reads two adjacent cmos bytes and return their values as a 16-bit word.
 */
uint16_t get_cmos_word(uint8_t idxFirst)
{
    return ((uint16_t)inb_cmos(idxFirst + 1) << 8)
         |            inb_cmos(idxFirst);
}

void BIOSCALL dummy_isr_function(pusha_regs_t regs, uint16_t es,
                                 uint16_t ds, iret_addr_t iret_addr)
{
    // Interrupt handler for unexpected hardware interrupts. We have to clear
    // the PIC because if we don't, the next EOI will clear the wrong interrupt
    // and all hell will break loose! This routine also masks the unexpected
    // interrupt so it will generally be called only once for each unexpected
    // interrupt level.
    uint8_t     isrA, isrB, imr, last_int = 0xFF;

    outb(PIC_MASTER, PIC_CMD_RD_ISR);           // Read master ISR
    isrA = inb(PIC_MASTER);
    if (isrA) {
        outb(PIC_SLAVE, PIC_CMD_RD_ISR);        // Read slave ISR
        isrB = inb(PIC_SLAVE);
        if (isrB) {
            imr = inb(PIC_SLAVE_MASK);
            outb(PIC_SLAVE_MASK, imr | isrB );  // Mask this interrupt
            outb(PIC_SLAVE, PIC_CMD_EOI);       // Send EOI on slave PIC
        } else {
            imr = inb(PIC_MASTER_MASK);
            isrA &= 0xFB;                       // Never mask the cascade interrupt
            outb(PIC_MASTER_MASK, imr | isrA);  // Mask this interrupt
        }
        outb(PIC_MASTER, PIC_CMD_EOI);          // Send EOI on master PIC
        last_int = isrA;
    }
    write_byte(0x40, 0x6B, last_int);           // Write INTR_FLAG
}


void BIOSCALL nmi_handler_msg(void)
{
    BX_PANIC("NMI Handler called\n");
}

void BIOSCALL int18_panic_msg(void)
{
    BX_INFO("INT18: BOOT FAILURE\n");
    out_ctrl_str_asm(VBOX_BIOS_SHUTDOWN_PORT, "Bootfail");
}

void BIOSCALL log_bios_start(void)
{
#if BX_DEBUG_SERIAL
    outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */
#endif
    BX_INFO("%s\n", bios_cvs_version_string);
}

/* Set video mode. */
void set_mode(uint8_t mode);
#pragma aux set_mode =      \
    "mov    ah, 0"          \
    "int    10h"            \
    parm [al] modify [ax];

/// @todo restore
//#undef VBOX

#define BX_PCIBIOS  1
#define BX_APPNAME          "VirtualBox"
#define BIOS_BUILD_DATE     __DATE__
//--------------------------------------------------------------------------
// print_bios_banner
//   displays a the bios version
//--------------------------------------------------------------------------
void BIOSCALL print_bios_banner(void)
{
#ifdef VBOX
    // Skip the logo if a warm boot is requested.
    uint16_t    warm_boot = read_word(0x0040,0x0072);
    write_word(0x0040,0x0072, 0);
    if (warm_boot == 0x1234)
    {
        /* Only set text mode. */
        set_mode(3);
        return;
    }
    /* show graphical logo */
    show_logo();
#else /* !VBOX */
    char        *bios_conf;

    /* Avoid using preprocessing directives within macro arguments. */
    bios_conf =
#ifdef __WATCOMC__
    "watcom "
#endif
#if BX_APM
    "apmbios "
#endif
#if BX_PCIBIOS
    "pcibios "
#endif
#if BX_ELTORITO_BOOT
    "eltorito "
#endif
#if BX_ROMBIOS32
    "rombios32 "
#endif
    "\n\n";

    printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
           BIOS_BUILD_DATE, bios_cvs_version_string);
    printf(bios_conf, 0);
#endif /* VBOX */
}