]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GnuGenBootSector/GnuGenBootSector.c
updated WinNtSerialIoDxe driver not to create new child handle if RemainingDeviepath...
[mirror_edk2.git] / BaseTools / Source / C / GnuGenBootSector / GnuGenBootSector.c
CommitLineData
30fdf114
LG
1/** @file\r
2\r
3Copyright 2006 - 2009, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
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
30//\r
31// Utility Name\r
32//\r
33#define UTILITY_NAME "GnuGenBootSector"\r
34\r
35//\r
36// Utility version information\r
37//\r
38#define UTILITY_MAJOR_VERSION 0\r
39#define UTILITY_MINOR_VERSION 1\r
40\r
41#define MAX_DRIVE 26\r
42#define PARTITION_TABLE_OFFSET 0x1BE\r
43\r
44#define SIZE_OF_PARTITION_ENTRY 0x10\r
45\r
46#define PARTITION_ENTRY_STARTLBA_OFFSET 8\r
47\r
48#define PARTITION_ENTRY_NUM 4\r
49\r
50#define DRIVE_UNKNOWN 0\r
51#define DRIVE_NO_ROOT_DIR 1\r
52#define DRIVE_REMOVABLE 2\r
53#define DRIVE_FIXED 3\r
54#define DRIVE_REMOTE 4\r
55#define DRIVE_CDROM 5\r
56#define DRIVE_RAMDISK 6\r
57\r
58typedef struct _DRIVE_TYPE_DESC {\r
59 UINTN Type;\r
60 CHAR8 *Description;\r
61} DRIVE_TYPE_DESC;\r
62\r
63#define DRIVE_TYPE_ITEM(x) {x, #x}\r
64\r
65DRIVE_TYPE_DESC DriveTypeDesc[] = {\r
66 DRIVE_TYPE_ITEM (DRIVE_UNKNOWN),\r
67 DRIVE_TYPE_ITEM (DRIVE_NO_ROOT_DIR),\r
68 DRIVE_TYPE_ITEM (DRIVE_REMOVABLE),\r
69 DRIVE_TYPE_ITEM (DRIVE_FIXED),\r
70 DRIVE_TYPE_ITEM (DRIVE_REMOTE),\r
71 DRIVE_TYPE_ITEM (DRIVE_CDROM),\r
72 DRIVE_TYPE_ITEM (DRIVE_RAMDISK),\r
73 {(UINTN) -1, NULL}\r
74};\r
75\r
76typedef struct _DRIVE_INFO {\r
77 CHAR8 VolumeLetter;\r
78 DRIVE_TYPE_DESC *DriveType;\r
79 UINTN DiskNumber;\r
80} DRIVE_INFO;\r
81\r
82typedef enum {\r
83 PathUnknown,\r
84 PathFile,\r
85 PathFloppy,\r
86 PathUsb,\r
87 PathIde\r
88} PATH_TYPE;\r
89\r
90typedef struct _PATH_INFO {\r
91 CHAR8 *Path;\r
92 CHAR8 PhysicalPath[260];\r
93 PATH_TYPE Type;\r
94 BOOLEAN Input;\r
95} PATH_INFO;\r
96\r
97typedef enum {\r
98 ErrorSuccess,\r
99 ErrorFileCreate,\r
100 ErrorFileReadWrite,\r
101 ErrorNoMbr,\r
102 ErrorFatType,\r
103 ErrorPath,\r
104} ERROR_STATUS;\r
105\r
106CHAR8 *ErrorStatusDesc[] = {\r
107 "Success",\r
108 "Failed to create files",\r
109 "Failed to read/write files",\r
110 "No MBR exists",\r
111 "Failed to detect Fat type",\r
112 "Inavlid path"\r
113};\r
114\r
115\r
116//UnSupported Windows API functions.\r
117UINTN GetLogicalDrives(void) { return 1; }\r
118\r
119\r
120\r
121/**\r
122 Get path information, including physical path for Linux platform.\r
123\r
124 @param PathInfo Point to PATH_INFO structure.\r
125\r
126 @return whether path is valid.\r
127**/\r
128ERROR_STATUS\r
129GetPathInfo (\r
130 PATH_INFO *PathInfo\r
131 )\r
132{\r
133 FILE *f;\r
134\r
135 if (strncmp(PathInfo->Path, "/dev/", 5) == 0) {\r
136 //\r
137 // Process disk path here.\r
138 // \r
139 \r
140 // Process floppy disk\r
141 if (PathInfo->Path[5] == 'f' && PathInfo->Path[6] == 'd' && PathInfo->Path[8] == '\0') {\r
142 PathInfo->Type = PathFloppy;\r
143 strcpy (PathInfo->PhysicalPath, PathInfo->Path);\r
144 \r
145 return ErrorSuccess;\r
146 } else {\r
147 // Other disk types is not supported yet.\r
148 fprintf (stderr, "ERROR: It's not a floppy disk!\n");\r
149 return ErrorPath;\r
150 } \r
151 \r
152 // Try to open the device. \r
153 f = fopen(PathInfo->Path,"r");\r
154 if (f == NULL) {\r
155 printf ("error :open device failed!\n");\r
156 return ErrorPath;\r
157 }\r
158 fclose (f);\r
159 return ErrorSuccess;\r
160 }\r
161 \r
162 // Process file path here.\r
163 PathInfo->Type = PathFile;\r
164 if (PathInfo->Input) {\r
165 // If path is file path, check whether file is valid.\r
166 printf("Path = %s\n",PathInfo->Path);\r
167 f = fopen (PathInfo->Path, "r");\r
168 if (f == NULL) {\r
169 fprintf (stderr, "Test error E2003: File was not provided!\n");\r
170 return ErrorPath;\r
171 }\r
172 fclose (f);\r
173 }\r
174\r
175 strcpy(PathInfo->PhysicalPath, PathInfo->Path);\r
176 return ErrorSuccess;\r
177\r
178}\r
179\r
180VOID\r
181ListDrive (\r
182 VOID\r
183 )\r
184{\r
185 printf("-l or -list not supported!\n");\r
186}\r
187\r
188/**\r
189 Writing or reading boot sector or MBR according to the argument. \r
190 \r
191 @param InputInfo PATH_INFO instance for input path\r
192 @param OutputInfo PATH_INFO instance for output path\r
193 @param ProcessMbr TRUE is to process MBR, otherwise, processing boot sector\r
194 \r
195 @return ERROR_STATUS\r
196 **/\r
197ERROR_STATUS\r
198ProcessBsOrMbr (\r
199 PATH_INFO *InputInfo,\r
200 PATH_INFO *OutputInfo,\r
201 BOOLEAN ProcessMbr\r
202 )\r
203{\r
204 CHAR8 FirstSector[0x200] = {0};\r
205 CHAR8 FirstSectorBackup[0x200] = {0};\r
206 \r
207 FILE *InputFile;\r
208 FILE *OutputFile;\r
209 \r
210 \r
211 InputFile = fopen(InputInfo->PhysicalPath, "r");\r
212 if (InputFile == NULL) {\r
213 return ErrorFileReadWrite;\r
214 }\r
215 \r
216 if (0x200 != fread(FirstSector, 1, 0x200, InputFile)) {\r
217 fclose(InputFile);\r
218 return ErrorFileReadWrite;\r
219 }\r
220 \r
221 fclose(InputFile);\r
222 \r
223 //Not support USB and IDE.\r
224 if (InputInfo->Type == PathUsb) {\r
225 printf("USB has not been supported yet!");\r
226 return ErrorSuccess;\r
227 }\r
228 \r
229 if (InputInfo->Type == PathIde) {\r
230 printf("IDE has not been supported yet!");\r
231 return ErrorSuccess;\r
232 } \r
233 \r
234 //Process Floppy Disk\r
235 OutputFile = fopen(OutputInfo->PhysicalPath, "w");\r
236 if (OutputFile == NULL) {\r
237 return ErrorFileReadWrite;\r
238 } \r
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
272 printf ("%s v%d.%d -Utility to retrieve and update the boot sector or MBR.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
273 printf ("Copyright (c) 2007-2009 Intel Corporation. All rights reserved.\n");\r
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
296INTN\r
297main (\r
298 INTN argc,\r
299 CHAR8 *argv[]\r
300 )\r
301{\r
302 CHAR8 *AppName;\r
303 INTN Index;\r
304 BOOLEAN ProcessMbr;\r
305 ERROR_STATUS Status;\r
306 EFI_STATUS EfiStatus;\r
307 PATH_INFO InputPathInfo;\r
308 PATH_INFO OutputPathInfo;\r
309 UINT64 LogLevel;\r
310\r
311 SetUtilityName (UTILITY_NAME);\r
312 \r
313 ZeroMem(&InputPathInfo, sizeof(PATH_INFO));\r
314 ZeroMem(&OutputPathInfo, sizeof(PATH_INFO));\r
315 \r
316 AppName = *argv;\r
317 argv ++;\r
318 argc --;\r
319 \r
320 ProcessMbr = FALSE;\r
321\r
322 if (argc == 0) {\r
323 PrintUsage();\r
324 return 0;\r
325 }\r
326 \r
327 //\r
328 // Parse command line\r
329 //\r
330 for (Index = 0; Index < argc; Index ++) {\r
331 if ((stricmp (argv[Index], "-l") == 0) || (stricmp (argv[Index], "--list") == 0)) {\r
332 ListDrive ();\r
333 return 0;\r
334 } \r
335 \r
336 if ((stricmp (argv[Index], "-m") == 0) || (stricmp (argv[Index], "--mbr") == 0)) {\r
337 ProcessMbr = TRUE;\r
338 continue;\r
339 }\r
340 \r
341 if ((stricmp (argv[Index], "-i") == 0) || (stricmp (argv[Index], "--input") == 0)) {\r
342 InputPathInfo.Path = argv[Index + 1];\r
343 InputPathInfo.Input = TRUE;\r
344 if (InputPathInfo.Path == NULL) {\r
345 Error (NULL, 0, 1003, "Invalid option value", "Input file name can't be NULL");\r
346 return 1;\r
347 } \r
348 if (InputPathInfo.Path[0] == '-') {\r
349 Error (NULL, 0, 1003, "Invalid option value", "Input file is missing");\r
350 return 1; \r
351 }\r
352 ++Index;\r
353 continue;\r
354 }\r
355 \r
356 if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {\r
357 OutputPathInfo.Path = argv[Index + 1];\r
358 OutputPathInfo.Input = FALSE;\r
359 if (OutputPathInfo.Path == NULL) {\r
360 Error (NULL, 0, 1003, "Invalid option value", "Output file name can't be NULL");\r
361 return 1;\r
362 } \r
363 if (OutputPathInfo.Path[0] == '-') {\r
364 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing");\r
365 return 1; \r
366 }\r
367 ++Index;\r
368 continue;\r
369 }\r
370 \r
371 if ((stricmp (argv[Index], "-h") == 0) || (stricmp (argv[Index], "--help") == 0)) {\r
372 PrintUsage ();\r
373 return 0;\r
374 }\r
375 \r
376 if (stricmp (argv[Index], "--version") == 0) {\r
377 Version ();\r
378 return 0;\r
379 } \r
380 \r
381 if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {\r
382 continue;\r
383 } \r
384 \r
385 if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {\r
386 continue;\r
387 } \r
388 \r
389 if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {\r
390 EfiStatus = AsciiStringToUint64 (argv[Index + 1], FALSE, &LogLevel);\r
391 if (EFI_ERROR (EfiStatus)) {\r
392 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);\r
393 return 1;\r
394 }\r
395 if (LogLevel > 9) {\r
396 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel);\r
397 return 1;\r
398 }\r
399 SetPrintLevel (LogLevel);\r
400 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[Index + 1]);\r
401 ++Index;\r
402 continue;\r
403 }\r
404\r
405 //\r
406 // Don't recognize the parameter.\r
407 //\r
408 Error (NULL, 0, 1000, "Unknown option", "%s", argv[Index]);\r
409 return 1;\r
410 }\r
411 \r
412 if (InputPathInfo.Path == NULL) {\r
413 Error (NULL, 0, 1001, "Missing options", "Input file is missing");\r
414 return 1;\r
415 }\r
416\r
417 if (OutputPathInfo.Path == NULL) {\r
418 Error (NULL, 0, 1001, "Missing options", "Output file is missing");\r
419 return 1;\r
420 }\r
421 \r
422 if (GetPathInfo(&InputPathInfo) != ErrorSuccess) {\r
423 Error (NULL, 0, 1003, "Invalid option value", "Input file can't be found.");\r
424 return 1;\r
425 }\r
426\r
427 if (GetPathInfo(&OutputPathInfo) != ErrorSuccess) {\r
428 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be found.");\r
429 return 1;\r
430 }\r
431 \r
432 //\r
433 // Process DBR (Patch or Read)\r
434 //\r
435 Status = ProcessBsOrMbr (&InputPathInfo, &OutputPathInfo, ProcessMbr);\r
436\r
437 if (Status == ErrorSuccess) {\r
438 fprintf (\r
439 stdout, \r
440 "%s %s: successful!\n", \r
441 (OutputPathInfo.Type != PathFile) ? "Write" : "Read", \r
442 ProcessMbr ? "MBR" : "DBR"\r
443 );\r
444 return 0;\r
445 } else {\r
446 fprintf (\r
447 stderr, \r
448 "%s: %s %s: failed - %s (LastError: 0x%x)!\n",\r
449 (Status == ErrorNoMbr) ? "WARNING" : "ERROR",\r
450 (OutputPathInfo.Type != PathFile) ? "Write" : "Read", \r
451 ProcessMbr ? "MBR" : "DBR", \r
452 ErrorStatusDesc[Status],\r
453 errno \r
454 );\r
455 return 1;\r
456 }\r
457}\r