VirtualBox

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

Last change on this file since 102277 was 102277, checked in by vboxsync, 18 months ago

bs3kit: Speed up high DLL loading by using a larger buffer. Extended the linker to process the segment table as well and output more appropriate address symbols in the base module assembly file. TODO: missing 16-bit selector setup in the bs3kit loader code. bugref:10371

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
Line 
1/* $Id: bs3-rm-InitHighDlls.c 102277 2023-11-23 15:43:31Z 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.215389.xyz.
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 //Bs3TestPrintf("cHighDlls=%d g_uBs3CpuDetected=%#x Bs3InitHighDlls_rm_far=%p\n", cHighDlls, g_uBs3CpuDetected, &Bs3InitHighDlls_rm_far);
55
56 if ( cHighDlls > 0
57 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
58 {
59 /*
60 * Get the drive geometry. ASSUMES the bootsector hasn't been trashed yet!
61 */
62 uint8_t const bDrive = ((BS3BOOTSECTOR RT_FAR *)BS3_FP_MAKE(0,0x7c00))->bBootDrv;
63 uint16_t uMaxCylinder = 0;
64 uint8_t uMaxHead = 0;
65 uint8_t uMaxSector = 0;
66 int rc = Bs3DiskQueryGeometry_rm(bDrive, &uMaxCylinder, &uMaxHead, &uMaxSector);
67 //Bs3TestPrintf("Bs3DiskQueryGeometry(%#x)-> C=%#x H=%#x S=%#x\n", bDrive, uMaxCylinder, uMaxHead, uMaxSector);
68 if (rc == 0)
69 {
70 uint16_t const cSectorsPerCylinder = uMaxSector * ((uint16_t)uMaxHead + 1);
71 unsigned i;
72
73 /*
74 * We need a buffer first of all. Using a 4K / PAGE_SIZE buffer let us
75 * share calculations and variables with the allocation code.
76 */
77 uint32_t uFlatBuf;
78 uint8_t cBufSectors;
79 uint8_t BS3_FAR *pbBuf;
80 uint16_t cbBuf = uMaxSector >= 72U ? 72U * 512U : uMaxSector * 512U;
81 void BS3_FAR *pvBufAllocated = Bs3MemAlloc(BS3MEMKIND_REAL, cbBuf);
82 if (!pbBuf)
83 {
84 cbBuf = _4K;
85 pvBufAllocated = Bs3MemAlloc(BS3MEMKIND_REAL, cbBuf);
86 if (!pvBufAllocated)
87 {
88 Bs3TestPrintf("Failed to allocate 4 KiB memory buffer for loading high DLL(s)!\n");
89 Bs3Shutdown();
90 }
91 }
92 cBufSectors = (uint8_t)(cbBuf / 512U);
93 uFlatBuf = BS3_FP_REAL_TO_FLAT(pvBufAllocated);
94 pbBuf = (uint8_t BS3_FAR *)BS3_FP_MAKE(uFlatBuf >> 4, 0); /* make sure the whole buffer is within a segment. */
95 /** @todo Is the above pbBuf hack necessary? */
96 //Bs3TestPrintf("pvBufAllocated=%p pbBuf=%p uFlatBuf=%RX32 cbBuf=%#x\n", pvBufAllocated, pbBuf, uFlatBuf, cbBuf);
97
98 /*
99 * Iterate the high DLL table and load it all into memory.
100 */
101 for (i = 0; i < cHighDlls; i++)
102 {
103 const char RT_FAR * const pszzStrings = (char RT_FAR *)&g_aBs3HighDllTable[i] + g_aBs3HighDllTable[i].offStrings;
104 const char RT_FAR * const pszFilename = &pszzStrings[g_aBs3HighDllTable[i].offFilename];
105 uint16_t const cPagesToLoad = (uint16_t)(g_aBs3HighDllTable[i].cbLoaded / _4K);
106 uint16_t iPage;
107 Bs3Printf("Loading dll '%s' at %#RX32..%#RX32 ...", pszFilename, g_aBs3HighDllTable[i].uLoadAddr,
108 g_aBs3HighDllTable[i].uLoadAddr + g_aBs3HighDllTable[i].cbLoaded - 1);
109
110 /*
111 * Allocate the memory taken by the DLL.
112 */
113 iPage = Bs3SlabAllocFixed(&g_Bs3Mem4KUpperTiled.Core, g_aBs3HighDllTable[i].uLoadAddr, cPagesToLoad);
114 if (iPage == 0 || iPage == UINT16_MAX)
115 {
116 Bs3TestPrintf("Bs3SlabAllocFixed(,%#RX32, %#RX16) failed: %#RX16 (%s)\n",
117 g_aBs3HighDllTable[i].uLoadAddr, cPagesToLoad, iPage, pszFilename);
118 Bs3Shutdown();
119 }
120 /** @todo We don't have any memory management above 16MB... */
121
122 /*
123 * Load the DLL. This is where we ASSUME real-mode, pre-PIC setup,
124 * and interrupts enabled as we need to use int13 for the actual
125 * reading. We switch to 32-bit protected mode and copies the
126 * chunk from pbBuf and to the actual load address.
127 *
128 * Note! When reading we must make sure to not switch head as the
129 * BIOS code messes up the result if it does the wraparound.
130 */
131 {
132
133 /* Load the image. */
134 {
135#ifdef BS3_WITH_LOAD_CHECKSUMS
136# if 0 /* for debugging */
137 uint32_t iCurSector = 0;
138# endif
139 uint32_t uChecksum = BS3_CALC_CHECKSUM_INITIAL_VALUE;
140#endif
141 uint32_t cSectorsLeftToLoad = g_aBs3HighDllTable[i].cbInImage / 512U;
142 uint32_t uCurFlatLoadAddr = g_aBs3HighDllTable[i].uLoadAddr;
143 /* Calculate the current CHS position: */
144 uint32_t const uCurSectorInImage = g_aBs3HighDllTable[i].offInImage / 512U;
145 uint16_t uCylinder = uCurSectorInImage / cSectorsPerCylinder;
146 uint16_t const uRemainder = uCurSectorInImage % cSectorsPerCylinder;
147 uint8_t uHead = uRemainder / uMaxSector;
148 uint8_t uSector = (uRemainder % uMaxSector) + 1;
149 while (cSectorsLeftToLoad > 0)
150 {
151 /* Figure out how much we dare read. Only up to the end of the track. */
152 uint8_t cSectors = uMaxSector + 1 - uSector;
153 if (cSectors > cBufSectors)
154 cSectors = cBufSectors;
155 if (cSectorsLeftToLoad < cSectors)
156 cSectors = (uint8_t)(cSectorsLeftToLoad);
157
158 //Bs3TestPrintf("Calling Bs3DiskRead(%#x,%#x,%#x,%#x,%#x,%p) [uCurFlatLoadAddr=%RX32]\n",
159 // bDrive, uCylinder, uHead, uSector, cSectors, pbBuf, uCurFlatLoadAddr);
160 rc = Bs3DiskRead_rm(bDrive, uCylinder, uHead, uSector, cSectors, pbBuf);
161 if (rc != 0)
162 {
163 Bs3TestPrintf("Bs3DiskRead(%#x,%#x,%#x,%#x,%#x,) failed: %#x\n",
164 bDrive, uCylinder, uHead, uSector, cBufSectors, rc);
165 Bs3Shutdown();
166 }
167
168#ifdef BS3_WITH_LOAD_CHECKSUMS
169 /* Checksum what we just loaded. */
170# if 0 /* For debugging. */
171 {
172 uint16_t j;
173 uint32_t uChecksumTmp = uChecksum;
174 for (j = 0; j < cSectors; j++, iCurSector++)
175 Bs3TestPrintf("sector #%RU32: %#RX32 %#010RX32\n", iCurSector,
176 uChecksumTmp = Bs3CalcChecksum(uChecksumTmp, &pbBuf[j * 512U], 512U),
177 Bs3CalcChecksum(BS3_CALC_CHECKSUM_INITIAL_VALUE, &pbBuf[j * 512U], 512U));
178 uChecksum = Bs3CalcChecksum(uChecksum, pbBuf, 512U * cSectors);
179 if (uChecksum != uChecksumTmp)
180 Bs3TestPrintf("Checksum error: %#RX32, expected %#RX32!\n", uChecksum, uChecksumTmp);
181 }
182# else
183 uChecksum = Bs3CalcChecksum(uChecksum, pbBuf, 512U * cSectors);
184# endif
185#endif
186
187 /* Copy the page to where the DLL is being loaded. */
188 Bs3MemCopyFlat_rm_far(uCurFlatLoadAddr, uFlatBuf, 512U * cSectors);
189 Bs3PrintChr('.');
190
191 /* Advance */
192 uCurFlatLoadAddr += cSectors * 512U;
193 cSectorsLeftToLoad -= cSectors;
194 uSector += cSectors;
195 if (!uSector || uSector > uMaxSector)
196 {
197 uSector = 1;
198 uHead++;
199 if (uHead > uMaxHead)
200 {
201 uHead = 0;
202 uCylinder++;
203 }
204 }
205 }
206
207#ifdef BS3_WITH_LOAD_CHECKSUMS
208 /* Verify the checksum. */
209 if (uChecksum != g_aBs3HighDllTable[i].uChecksum)
210 {
211 Bs3TestPrintf("Checksum mismatch for '%s': %#RX32 vs %#RX32\n",
212 pszFilename, uChecksum, g_aBs3HighDllTable[i].uChecksum);
213 Bs3Shutdown();
214 }
215#endif
216 }
217 }
218 }
219
220 Bs3Printf("\n");
221 Bs3MemFree(pvBufAllocated, cbBuf);
222 }
223 else
224 {
225 Bs3TestPrintf("Bs3DiskQueryGeometry(%#x) failed: %#x\n", bDrive, rc);
226 Bs3Shutdown();
227 }
228 }
229}
230
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