]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GnuGenBootSector/GnuGenBootSector.c
Sync BaseTools Branch (version r2321) to EDKII main trunk.
[mirror_edk2.git] / BaseTools / Source / C / GnuGenBootSector / GnuGenBootSector.c
1 /** @file
2
3 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 GnuGenBootSector.c
15
16 Abstract:
17 Reading/writing MBR/DBR.
18 NOTE:
19 If we write MBR to disk, we just update the MBR code and the partition table wouldn't be over written.
20 If we process DBR, we will patch MBR to set first partition active if no active partition exists.
21
22 **/
23
24 #include "CommonLib.h"
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <Common/UefiBaseTypes.h>
29
30 #include "ParseInf.h"
31 #include "EfiUtilityMsgs.h"
32
33 //
34 // Utility Name
35 //
36 #define UTILITY_NAME "GnuGenBootSector"
37
38 //
39 // Utility version information
40 //
41 #define UTILITY_MAJOR_VERSION 0
42 #define UTILITY_MINOR_VERSION 1
43
44 #define MAX_DRIVE 26
45 #define PARTITION_TABLE_OFFSET 0x1BE
46
47 #define SIZE_OF_PARTITION_ENTRY 0x10
48
49 #define PARTITION_ENTRY_STARTLBA_OFFSET 8
50
51 #define PARTITION_ENTRY_NUM 4
52
53 #define DRIVE_UNKNOWN 0
54 #define DRIVE_NO_ROOT_DIR 1
55 #define DRIVE_REMOVABLE 2
56 #define DRIVE_FIXED 3
57 #define DRIVE_REMOTE 4
58 #define DRIVE_CDROM 5
59 #define DRIVE_RAMDISK 6
60
61 typedef struct _DRIVE_TYPE_DESC {
62 UINTN Type;
63 CHAR8 *Description;
64 } DRIVE_TYPE_DESC;
65
66 #define DRIVE_TYPE_ITEM(x) {x, #x}
67
68 DRIVE_TYPE_DESC DriveTypeDesc[] = {
69 DRIVE_TYPE_ITEM (DRIVE_UNKNOWN),
70 DRIVE_TYPE_ITEM (DRIVE_NO_ROOT_DIR),
71 DRIVE_TYPE_ITEM (DRIVE_REMOVABLE),
72 DRIVE_TYPE_ITEM (DRIVE_FIXED),
73 DRIVE_TYPE_ITEM (DRIVE_REMOTE),
74 DRIVE_TYPE_ITEM (DRIVE_CDROM),
75 DRIVE_TYPE_ITEM (DRIVE_RAMDISK),
76 {(UINTN) -1, NULL}
77 };
78
79 typedef struct _DRIVE_INFO {
80 CHAR8 VolumeLetter;
81 DRIVE_TYPE_DESC *DriveType;
82 UINTN DiskNumber;
83 } DRIVE_INFO;
84
85 typedef enum {
86 PathUnknown,
87 PathFile,
88 PathFloppy,
89 PathUsb,
90 PathIde
91 } PATH_TYPE;
92
93 typedef struct _PATH_INFO {
94 CHAR8 *Path;
95 CHAR8 PhysicalPath[260];
96 PATH_TYPE Type;
97 BOOLEAN Input;
98 } PATH_INFO;
99
100 typedef enum {
101 ErrorSuccess,
102 ErrorFileCreate,
103 ErrorFileReadWrite,
104 ErrorNoMbr,
105 ErrorFatType,
106 ErrorPath,
107 } ERROR_STATUS;
108
109 CHAR8 *ErrorStatusDesc[] = {
110 "Success",
111 "Failed to create files",
112 "Failed to read/write files",
113 "No MBR exists",
114 "Failed to detect Fat type",
115 "Inavlid path"
116 };
117
118
119 //UnSupported Windows API functions.
120 UINTN GetLogicalDrives(void) { return 1; }
121
122
123
124 /**
125 Get path information, including physical path for Linux platform.
126
127 @param PathInfo Point to PATH_INFO structure.
128
129 @return whether path is valid.
130 **/
131 ERROR_STATUS
132 GetPathInfo (
133 PATH_INFO *PathInfo
134 )
135 {
136 FILE *f;
137
138 if (strncmp(PathInfo->Path, "/dev/", 5) == 0) {
139 //
140 // Process disk path here.
141 //
142
143 // Process floppy disk
144 if (PathInfo->Path[5] == 'f' && PathInfo->Path[6] == 'd' && PathInfo->Path[8] == '\0') {
145 PathInfo->Type = PathFloppy;
146 strcpy (PathInfo->PhysicalPath, PathInfo->Path);
147
148 return ErrorSuccess;
149 } else {
150 // Other disk types is not supported yet.
151 fprintf (stderr, "ERROR: It's not a floppy disk!\n");
152 return ErrorPath;
153 }
154
155 // Try to open the device.
156 f = fopen(PathInfo->Path,"r");
157 if (f == NULL) {
158 printf ("error :open device failed!\n");
159 return ErrorPath;
160 }
161 fclose (f);
162 return ErrorSuccess;
163 }
164
165 // Process file path here.
166 PathInfo->Type = PathFile;
167 if (PathInfo->Input) {
168 // If path is file path, check whether file is valid.
169 printf("Path = %s\n",PathInfo->Path);
170 f = fopen (PathInfo->Path, "r");
171 if (f == NULL) {
172 fprintf (stderr, "Test error E2003: File was not provided!\n");
173 return ErrorPath;
174 }
175 fclose (f);
176 }
177
178 strcpy(PathInfo->PhysicalPath, PathInfo->Path);
179 return ErrorSuccess;
180
181 }
182
183 VOID
184 ListDrive (
185 VOID
186 )
187 {
188 printf("-l or -list not supported!\n");
189 }
190
191 /**
192 Writing or reading boot sector or MBR according to the argument.
193
194 @param InputInfo PATH_INFO instance for input path
195 @param OutputInfo PATH_INFO instance for output path
196 @param ProcessMbr TRUE is to process MBR, otherwise, processing boot sector
197
198 @return ERROR_STATUS
199 **/
200 ERROR_STATUS
201 ProcessBsOrMbr (
202 PATH_INFO *InputInfo,
203 PATH_INFO *OutputInfo,
204 BOOLEAN ProcessMbr
205 )
206 {
207 CHAR8 FirstSector[0x200] = {0};
208 CHAR8 FirstSectorBackup[0x200] = {0};
209
210 FILE *InputFile;
211 FILE *OutputFile;
212
213
214 InputFile = fopen(InputInfo->PhysicalPath, "r");
215 if (InputFile == NULL) {
216 return ErrorFileReadWrite;
217 }
218
219 if (0x200 != fread(FirstSector, 1, 0x200, InputFile)) {
220 fclose(InputFile);
221 return ErrorFileReadWrite;
222 }
223
224 fclose(InputFile);
225
226 //Not support USB and IDE.
227 if (InputInfo->Type == PathUsb) {
228 printf("USB has not been supported yet!");
229 return ErrorSuccess;
230 }
231
232 if (InputInfo->Type == PathIde) {
233 printf("IDE has not been supported yet!");
234 return ErrorSuccess;
235 }
236
237 //Process Floppy Disk
238 OutputFile = fopen(OutputInfo->PhysicalPath, "r+");
239 if (OutputFile == NULL) {
240 OutputFile = fopen(OutputInfo->PhysicalPath, "w");
241 if (OutputFile == NULL) {
242 return ErrorFileReadWrite;
243 }
244 }
245
246 if (OutputInfo->Type != PathFile) {
247 if (ProcessMbr) {
248 //
249 // Use original partition table
250 //
251 if (0x200 != fread (FirstSectorBackup, 1, 0x200, OutputFile)) {
252 fclose(OutputFile);
253 return ErrorFileReadWrite;
254 }
255 memcpy (FirstSector + 0x1BE, FirstSectorBackup + 0x1BE, 0x40);
256 }
257 }
258 if(0x200 != fwrite(FirstSector, 1, 0x200, OutputFile)) {
259 fclose(OutputFile);
260 return ErrorFileReadWrite;
261 }
262
263 fclose(OutputFile);
264 return ErrorSuccess;
265 }
266
267
268 /**
269
270 Displays the standard utility information to SDTOUT
271
272 **/
273 VOID
274 Version (
275 VOID
276 )
277 {
278 printf ("%s v%d.%d %s-Utility to retrieve and update the boot sector or MBR.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
279 printf ("Copyright (c) 2007-2010 Intel Corporation. All rights reserved.\n");
280 }
281
282
283 VOID
284 PrintUsage (
285 VOID
286 )
287 {
288 Version();
289 printf ("\nUsage: \n\
290 GenBootSector\n\
291 [-l, --list list disks]\n\
292 [-i, --input Filename]\n\
293 [-o, --output Filename]\n\
294 [-m, --mbr process the MBR also]\n\
295 [-v, --verbose]\n\
296 [--version]\n\
297 [-q, --quiet disable all messages except fatal errors]\n\
298 [-d, --debug[#]\n\
299 [-h, --help]\n");
300 }
301
302 int
303 main (
304 int argc,
305 char *argv[]
306 )
307 {
308 CHAR8 *AppName;
309 INTN Index;
310 BOOLEAN ProcessMbr;
311 ERROR_STATUS Status;
312 EFI_STATUS EfiStatus;
313 PATH_INFO InputPathInfo;
314 PATH_INFO OutputPathInfo;
315 UINT64 LogLevel;
316
317 SetUtilityName (UTILITY_NAME);
318
319 ZeroMem(&InputPathInfo, sizeof(PATH_INFO));
320 ZeroMem(&OutputPathInfo, sizeof(PATH_INFO));
321
322 AppName = *argv;
323 argv ++;
324 argc --;
325
326 ProcessMbr = FALSE;
327
328 if (argc == 0) {
329 PrintUsage();
330 return 0;
331 }
332
333 //
334 // Parse command line
335 //
336 for (Index = 0; Index < argc; Index ++) {
337 if ((stricmp (argv[Index], "-l") == 0) || (stricmp (argv[Index], "--list") == 0)) {
338 ListDrive ();
339 return 0;
340 }
341
342 if ((stricmp (argv[Index], "-m") == 0) || (stricmp (argv[Index], "--mbr") == 0)) {
343 ProcessMbr = TRUE;
344 continue;
345 }
346
347 if ((stricmp (argv[Index], "-i") == 0) || (stricmp (argv[Index], "--input") == 0)) {
348 InputPathInfo.Path = argv[Index + 1];
349 InputPathInfo.Input = TRUE;
350 if (InputPathInfo.Path == NULL) {
351 Error (NULL, 0, 1003, "Invalid option value", "Input file name can't be NULL");
352 return 1;
353 }
354 if (InputPathInfo.Path[0] == '-') {
355 Error (NULL, 0, 1003, "Invalid option value", "Input file is missing");
356 return 1;
357 }
358 ++Index;
359 continue;
360 }
361
362 if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {
363 OutputPathInfo.Path = argv[Index + 1];
364 OutputPathInfo.Input = FALSE;
365 if (OutputPathInfo.Path == NULL) {
366 Error (NULL, 0, 1003, "Invalid option value", "Output file name can't be NULL");
367 return 1;
368 }
369 if (OutputPathInfo.Path[0] == '-') {
370 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing");
371 return 1;
372 }
373 ++Index;
374 continue;
375 }
376
377 if ((stricmp (argv[Index], "-h") == 0) || (stricmp (argv[Index], "--help") == 0)) {
378 PrintUsage ();
379 return 0;
380 }
381
382 if (stricmp (argv[Index], "--version") == 0) {
383 Version ();
384 return 0;
385 }
386
387 if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {
388 continue;
389 }
390
391 if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {
392 continue;
393 }
394
395 if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {
396 EfiStatus = AsciiStringToUint64 (argv[Index + 1], FALSE, &LogLevel);
397 if (EFI_ERROR (EfiStatus)) {
398 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);
399 return 1;
400 }
401 if (LogLevel > 9) {
402 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel);
403 return 1;
404 }
405 SetPrintLevel (LogLevel);
406 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[Index + 1]);
407 ++Index;
408 continue;
409 }
410
411 //
412 // Don't recognize the parameter.
413 //
414 Error (NULL, 0, 1000, "Unknown option", "%s", argv[Index]);
415 return 1;
416 }
417
418 if (InputPathInfo.Path == NULL) {
419 Error (NULL, 0, 1001, "Missing options", "Input file is missing");
420 return 1;
421 }
422
423 if (OutputPathInfo.Path == NULL) {
424 Error (NULL, 0, 1001, "Missing options", "Output file is missing");
425 return 1;
426 }
427
428 if (GetPathInfo(&InputPathInfo) != ErrorSuccess) {
429 Error (NULL, 0, 1003, "Invalid option value", "Input file can't be found.");
430 return 1;
431 }
432
433 if (GetPathInfo(&OutputPathInfo) != ErrorSuccess) {
434 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be found.");
435 return 1;
436 }
437
438 //
439 // Process DBR (Patch or Read)
440 //
441 Status = ProcessBsOrMbr (&InputPathInfo, &OutputPathInfo, ProcessMbr);
442
443 if (Status == ErrorSuccess) {
444 fprintf (
445 stdout,
446 "%s %s: successful!\n",
447 (OutputPathInfo.Type != PathFile) ? "Write" : "Read",
448 ProcessMbr ? "MBR" : "DBR"
449 );
450 return 0;
451 } else {
452 fprintf (
453 stderr,
454 "%s: %s %s: failed - %s (LastError: 0x%x)!\n",
455 (Status == ErrorNoMbr) ? "WARNING" : "ERROR",
456 (OutputPathInfo.Type != PathFile) ? "Write" : "Read",
457 ProcessMbr ? "MBR" : "DBR",
458 ErrorStatusDesc[Status],
459 errno
460 );
461 return 1;
462 }
463 }