VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitHighDlls.c@ 102181

Last change on this file since 102181 was 102181, checked in by vboxsync, 17 months ago

ValKit/bs3kit: High DLL loading fixes (keep forgetting the BIOS doesn't like advancing the head). Expanded the export entry so it's safe to use the pointers from 64-bit code. Prepped for sel:offset addressing of 16-bit code in high dll as well. bugref:10371

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.4 KB
Line 
1/* $Id: bs3-rm-InitHighDlls.c 102181 2023-11-21 09:45:40Z vboxsync $ */
2/** @file
3 * BS3Kit - Initialize any high DLLs, real mode.
4 */
5
6/*
7 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41//#define BS3_USE_RM_TEXT_SEG 1
42#include "bs3kit-template-header.h"
43#include "bs3kit-linker.h"
44#include "bs3-cmn-memory.h"
45
46
47extern BS3HIGHDLLENTRY BS3_FAR_DATA BS3_DATA_NM(g_aBs3HighDllTable)[];
48extern BS3HIGHDLLENTRY BS3_FAR_DATA BS3_DATA_NM(g_Bs3HighDllTable_End);
49
50
51BS3_DECL_FAR(void) Bs3InitHighDlls_rm_far(void)
52{
53 unsigned const cHighDlls = (unsigned)(&g_Bs3HighDllTable_End - &g_aBs3HighDllTable[0]);
54 if ( cHighDlls > 0
55 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
56 {
57 unsigned i;
58
59 /*
60 * We need a buffer first of all. Using a 4K / PAGE_SIZE buffer let us
61 * share calculations and variables with the allocation code.
62 */
63 uint32_t uFlatBuf;
64 uint8_t cBufSectors;
65 uint16_t cbBuf = 12*_1K; /* This is typically enough for a track (512*18 = 0x2400 (9216)). */
66 void BS3_FAR *pvBuf = Bs3MemAlloc(BS3MEMKIND_REAL, cbBuf);
67 if (!pvBuf)
68 {
69 cbBuf = _4K;
70 pvBuf = Bs3MemAlloc(BS3MEMKIND_REAL, cbBuf);
71 if (!pvBuf)
72 {
73 Bs3TestPrintf("Failed to allocate 4 KiB memory buffer for loading high DLL(s)!\n");
74 Bs3Shutdown();
75 }
76 }
77 cBufSectors = (uint8_t)(cbBuf / 512);
78 uFlatBuf = BS3_FP_REAL_TO_FLAT(pvBuf);
79
80 /*
81 * Iterate the high DLL table and load it all into memory.
82 */
83 for (i = 0; i < cHighDlls; i++)
84 {
85 const char RT_FAR * const pszzStrings = (char RT_FAR *)&g_aBs3HighDllTable[i] + g_aBs3HighDllTable[i].offStrings;
86 const char RT_FAR * const pszFilename = &pszzStrings[g_aBs3HighDllTable[i].offFilename];
87 uint16_t const cPagesToLoad = (uint16_t)(g_aBs3HighDllTable[i].cbLoaded / _4K);
88 uint16_t iPage;
89 Bs3Printf("Loading dll '%s' at %#RX32 ...", pszFilename, g_aBs3HighDllTable[i].uLoadAddr);
90
91 /*
92 * Allocate the memory taken by the DLL.
93 */
94 iPage = Bs3SlabAllocFixed(&g_Bs3Mem4KUpperTiled.Core, g_aBs3HighDllTable[i].uLoadAddr, cPagesToLoad);
95 if (iPage == 0 || iPage == UINT16_MAX)
96 {
97 Bs3TestPrintf("Bs3SlabAllocFixed(,%#RX32, %#RX16) failed: %#RX16 (%s)\n",
98 g_aBs3HighDllTable[i].uLoadAddr, cPagesToLoad, iPage, pszFilename);
99 Bs3Shutdown();
100 }
101 /** @todo We don't have any memory management above 16MB... */
102
103 /*
104 * Load the DLL. This is where we ASSUME real-mode, pre-PIC setup,
105 * and interrupts enabled as we need to use int13 for the actual
106 * reading. We switch to 32-bit protected mode and copies the
107 * chunk from pvBuf and to the actual load address.
108 *
109 * Note! When reading we must make sure to not switch head as the
110 * BIOS code messes up the result if it does the wraparound.
111 */
112 {
113 /* Get the drive geometry. ASSUMES the bootsector hasn't been trashed yet! */
114 uint16_t cSectorsPerCylinder;
115 uint8_t const bDrive = ((BS3BOOTSECTOR RT_FAR *)BS3_FP_MAKE(0,0x7c00))->bBootDrv;
116 uint16_t uMaxCylinder = 0;
117 uint8_t uMaxHead = 0;
118 uint8_t uMaxSector = 0;
119 int rc = Bs3DiskQueryGeometry_rm(bDrive, &uMaxCylinder, &uMaxHead, &uMaxSector);
120 if (rc != 0)
121 {
122 Bs3TestPrintf("Bs3DiskQueryGeometry(%#x) failed: %#x\n", bDrive, rc);
123 Bs3Shutdown();
124 }
125 cSectorsPerCylinder = uMaxSector * ((uint16_t)uMaxHead + 1);
126 //Bs3TestPrintf("Bs3DiskQueryGeometry(%#x)-> C=%#x H=%#x S=%#x cSectorsPerCylinder=%#x\n",
127 // bDrive, uMaxCylinder, uMaxHead, uMaxSector, cSectorsPerCylinder);
128
129 /* Load the image. */
130 {
131 uint32_t cSectorsLeftToLoad = g_aBs3HighDllTable[i].cbInImage / 512;
132 uint32_t uCurFlatLoadAddr = g_aBs3HighDllTable[i].uLoadAddr;
133 /* Calculate the current CHS position: */
134 uint32_t const uCurSectorInImage = g_aBs3HighDllTable[i].offInImage / 512;
135 uint16_t uCylinder = uCurSectorInImage / cSectorsPerCylinder;
136 uint16_t const uRemainder = uCurSectorInImage % cSectorsPerCylinder;
137 uint8_t uHead = uRemainder / uMaxSector;
138 uint8_t uSector = (uRemainder % uMaxSector) + 1;
139 while (cSectorsLeftToLoad > 0)
140 {
141 /* Figure out how much we dare read. Only up to the end of the track. */
142 uint8_t cSectors = uMaxSector + 1 - uSector;
143 if (cSectors > cBufSectors)
144 cSectors = cBufSectors;
145 if (cSectorsLeftToLoad < cSectors)
146 cSectors = (uint8_t)(cSectorsLeftToLoad);
147
148 //Bs3TestPrintf("Calling Bs3DiskRead(%#x,%#x,%#x,%#x,%#x,%p) [uCurFlatLoadAddr=%RX32]\n",
149 // bDrive, uCylinder, uHead, uSector, cSectors, pvBuf, uCurFlatLoadAddr);
150 rc = Bs3DiskRead_rm(bDrive, uCylinder, uHead, uSector, cSectors, pvBuf);
151 if (rc != 0)
152 {
153 Bs3TestPrintf("Bs3DiskRead(%#x,%#x,%#x,%#x,%#x,) failed: %#x\n",
154 bDrive, uCylinder, uHead, uSector, cBufSectors, rc);
155 Bs3Shutdown();
156 }
157
158 /* Copy the page to where the DLL is being loaded. */
159 Bs3MemCopyFlat_rm_far(uCurFlatLoadAddr, uFlatBuf, 512 * cSectors);
160 Bs3PrintChr('.');
161
162 /* Advance */
163 uCurFlatLoadAddr += cSectors * 512;
164 cSectorsLeftToLoad -= cSectors;
165 uSector += cSectors;
166 if (uSector > uMaxSector)
167 {
168 uSector = 1;
169 uHead++;
170 if (uHead > uMaxHead)
171 {
172 uHead = 0;
173 uCylinder++;
174 }
175 }
176 }
177 }
178 }
179 }
180
181 Bs3Printf("\n");
182 Bs3MemFree(pvBuf, cbBuf);
183 }
184}
185
Note: See TracBrowser for help on using the repository browser.

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