VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3Linker.cpp@ 58633

最後變更 在這個檔案從58633是 58633,由 vboxsync 提交於 9 年 前

VBoxBs3Linker.cpp: warning.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 11.8 KB
 
1/* $Id: VBoxBs3Linker.cpp 58633 2015-11-10 12:28:06Z vboxsync $ */
2/** @file
3 * VirtualBox Validation Kit - Boot Sector 3 "linker".
4 */
5
6/*
7 * Copyright (C) 2006-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <stdio.h>
32#include <string.h>
33#include <stdlib.h>
34#include <iprt/types.h>
35#include <iprt/assert.h>
36
37
38/*********************************************************************************************************************************
39* Structures and Typedefs *
40*********************************************************************************************************************************/
41#pragma pack(1)
42typedef struct BS3BOOTSECTOR
43{
44 uint8_t abJmp[3];
45 char abOemId[8];
46 /** @name EBPB, DOS 4.0 style.
47 * @{ */
48 uint16_t cBytesPerSector; /**< 00bh */
49 uint8_t cSectorsPerCluster; /**< 00dh */
50 uint16_t cReservedSectors; /**< 00eh */
51 uint8_t cFATs; /**< 010h */
52 uint16_t cRootDirEntries; /**< 011h */
53 uint16_t cTotalSectors; /**< 013h */
54 uint8_t bMediaDescriptor; /**< 015h */
55 uint16_t cSectorsPerFAT; /**< 016h */
56 uint16_t cPhysSectorsPerTrack; /**< 018h */
57 uint16_t cHeads; /**< 01ah */
58 uint32_t cHiddentSectors; /**< 01ch */
59 uint32_t cLargeTotalSectors; /**< 020h - We (ab)use this to indicate the number of sectors to load. */
60 uint8_t bBootDrv; /**< 024h */
61 uint8_t bFlagsEtc; /**< 025h */
62 uint8_t bExtendedSignature; /**< 026h */
63 uint32_t dwSerialNumber; /**< 027h */
64 char abLabel[11]; /**< 02bh */
65 char abFSType[8]; /**< 036h */
66 /** @} */
67} BS3BOOTSECTOR;
68#pragma pack()
69typedef BS3BOOTSECTOR *PBS3BOOTSECTOR;
70
71AssertCompileMemberOffset(BS3BOOTSECTOR, cLargeTotalSectors, 0x20);
72AssertCompileMemberOffset(BS3BOOTSECTOR, abLabel, 0x2b);
73AssertCompileMemberOffset(BS3BOOTSECTOR, abFSType, 0x36);
74
75#define BS3_OEMID "BS3Kit\n\n"
76#define BS3_FSTYPE "RawCode\n"
77#define BS3_LABEL "VirtualBox\n"
78#define BS3_MAX_SIZE UINT32_C(491520) /* 480KB */
79
80
81int main(int argc, char **argv)
82{
83 const char *pszOutput = NULL;
84 struct BS3LNKINPUT
85 {
86 const char *pszFile;
87 FILE *pFile;
88 uint32_t cbFile;
89 } *paInputs = (struct BS3LNKINPUT *)calloc(sizeof(paInputs[0]), argc);
90 unsigned cInputs = 0;
91 uint32_t cSectors = 0;
92
93 /*
94 * Scan the arguments.
95 */
96 for (int i = 1; i < argc; i++)
97 {
98 if (argv[i][0] == '-')
99 {
100 const char *pszOpt = &argv[i][1];
101 if (*pszOpt == '-')
102 {
103 /* Convert long options to short ones. */
104 pszOpt--;
105 if (!strcmp(pszOpt, "--output"))
106 pszOpt = "o";
107 else if (!strcmp(pszOpt, "--version"))
108 pszOpt = "V";
109 else if (!strcmp(pszOpt, "--help"))
110 pszOpt = "h";
111 else
112 {
113 fprintf(stderr, "syntax errro: Unknown options '%s'\n", pszOpt);
114 free(paInputs);
115 return 2;
116 }
117 }
118
119 /* Process the list of short options. */
120 while (*pszOpt)
121 {
122 switch (*pszOpt++)
123 {
124 case 'o':
125 {
126 const char *pszValue = pszOpt;
127 pszOpt = strchr(pszOpt, '\0');
128 if (*pszValue == '=')
129 pszValue++;
130 else if (!*pszValue)
131 {
132 if (i + 1 >= argc)
133 {
134 fprintf(stderr, "syntax error: The --output option expects a filename.\n");
135 return 12;
136 }
137 pszValue = argv[++i];
138 }
139 if (pszOutput)
140 {
141 fprintf(stderr, "Only one output file is allowed. You've specified '%s' and '%s'\n",
142 pszOutput, pszValue);
143 return 2;
144 }
145 pszOutput = pszValue;
146 pszOpt = "";
147 break;
148 }
149
150 case 'V':
151 printf("%s\n", "$Revision: 58633 $");
152 return 0;
153
154 case '?':
155 case 'h':
156 printf("usage: %s [options] -o <output> <input1> [input2 ... [inputN]]\n",
157 argv[0]);
158 return 0;
159 }
160 }
161 }
162 else
163 {
164 /*
165 * Add to input file collection.
166 */
167 paInputs[cInputs].pszFile = argv[i];
168#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
169 FILE *pFile = fopen(paInputs[cInputs].pszFile, "rb");
170#else
171 FILE *pFile = fopen(paInputs[cInputs].pszFile, "r");
172#endif
173 if (pFile)
174 {
175 if (fseek(pFile, 0, SEEK_END) == 0)
176 {
177 paInputs[cInputs].cbFile = (uint32_t)ftell(pFile);
178 if (fseek(pFile, 0, SEEK_SET) == 0)
179 {
180 if (cInputs != 0 || paInputs[cInputs].cbFile == 512)
181 {
182 cSectors += RT_ALIGN_32(paInputs[cInputs].cbFile, 512) / 512;
183 if (cSectors <= BS3_MAX_SIZE / 512)
184 {
185 if (cSectors > 0)
186 {
187 paInputs[cInputs].pFile = pFile;
188 pFile = NULL;
189 }
190 else
191 fprintf(stderr, "error: empty input file: '%s'\n", paInputs[cInputs].pszFile);
192 }
193 else
194 fprintf(stderr, "error: input is too big: %u bytes, %u sectors (max %u bytes, %u sectors)\n"
195 "info: detected loading '%s'\n",
196 cSectors * 512, cSectors, BS3_MAX_SIZE, BS3_MAX_SIZE / 512,
197 paInputs[cInputs].pszFile);
198 }
199 else
200 fprintf(stderr, "error: first input file (%s) must be exactly 512 bytes\n", paInputs[cInputs].pszFile);
201 }
202 else
203 fprintf(stderr, "error: seeking to start of '%s' failed\n", paInputs[cInputs].pszFile);
204 }
205 else
206 fprintf(stderr, "error: seeking to end of '%s' failed\n", paInputs[cInputs].pszFile);
207 }
208 else
209 fprintf(stderr, "error: Failed to open input file '%s' for reading\n", paInputs[cInputs].pszFile);
210 if (pFile)
211 return 1;
212 cInputs++;
213 }
214 }
215
216 if (!pszOutput)
217 {
218 fprintf(stderr, "syntax error: No output file was specified (-o or --output).\n");
219 return 2;
220 }
221 if (cInputs == 0)
222 {
223 fprintf(stderr, "syntax error: No input files was specified.\n");
224 return 2;
225 }
226
227 /*
228 * Do the job.
229 */
230 /* Open the output file. */
231#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
232 FILE *pOutput = fopen(pszOutput, "wb");
233#else
234 FILE *pOutput = fopen(pszOutput, "w");
235#endif
236 if (!pOutput)
237 {
238 fprintf(stderr, "error: Failed to open output file '%s' for writing\n", pszOutput);
239 return 1;
240 }
241
242 /* Copy the input files to the output file, with sector padding applied. */
243 int rcExit = 0;
244 size_t off = 0;
245 for (unsigned i = 0; i < cInputs && rcExit == 0; i++)
246 {
247 uint8_t abBuf[4096]; /* Must be multiple of 512! */
248 uint32_t cbToRead = paInputs[i].cbFile;
249 while (cbToRead > 0)
250 {
251 /* Read a block from the input file. */
252 uint32_t const cbThisRead = RT_MIN(cbToRead, sizeof(abBuf));
253 size_t cbRead = fread(abBuf, sizeof(uint8_t), cbThisRead, paInputs[i].pFile);
254 if (cbRead != cbThisRead)
255 {
256 fprintf(stderr, "error: Error reading '%s' (got %d bytes, wanted %u).\n",
257 paInputs[i].pszFile, (int)cbRead, (unsigned)cbThisRead);
258 rcExit = 1;
259 break;
260 }
261 cbToRead -= cbThisRead;
262
263 /* Padd the end of the file if necessary. */
264 if ((cbRead & 0x1ff) != 0)
265 {
266 memset(&abBuf[cbRead], 0, 4096 - cbRead);
267 cbRead = (cbRead + 0x1ff) & ~0x1ffU;
268 }
269
270 /* Patch the BPB of the first file. */
271 if (off == 0)
272 {
273 PBS3BOOTSECTOR pBs = (PBS3BOOTSECTOR)&abBuf[0];
274 if ( memcmp(pBs->abLabel, RT_STR_TUPLE(BS3_LABEL)) == 0
275 && memcmp(pBs->abFSType, RT_STR_TUPLE(BS3_FSTYPE)) == 0
276 && memcmp(pBs->abOemId, RT_STR_TUPLE(BS3_OEMID)) == 0)
277 pBs->cLargeTotalSectors = cSectors;
278 else
279 {
280 fprintf(stderr, "error: Didn't find magic strings in the first file (%s).\n", paInputs[i].pszFile);
281 rcExit = 1;
282 }
283 }
284
285 /* Write the block to the output file. */
286 if (fwrite(abBuf, sizeof(uint8_t), cbRead, pOutput) == cbRead)
287 off += cbRead;
288 else
289 {
290 fprintf(stderr, "error: fwrite failed\n");
291 rcExit = 1;
292 break;
293 }
294 }
295
296 if (ferror(paInputs[i].pFile))
297 {
298 fprintf(stderr, "error: Error reading '%s'.\n", paInputs[i].pszFile);
299 rcExit = 1;
300 }
301 }
302
303 /* Close the input files. */
304 for (unsigned i = 0; i < cInputs && rcExit == 0; i++)
305 fclose(paInputs[i].pFile);
306 free(paInputs);
307
308 /* Finally, close the output file (can fail because of buffered data). */
309 if (fclose(stderr) != 0)
310 {
311 fprintf(stderr, "error: Error closing '%s'.\n", pszOutput);
312 rcExit = 1;
313 }
314
315 fclose(pOutput);
316 return rcExit;
317}
318
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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