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