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