]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenBootSector/GenBootSector.c
Sync BaseTools Branch (version r2321) to EDKII main trunk.
[mirror_edk2.git] / BaseTools / Source / C / GenBootSector / GenBootSector.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 genbootsector.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 <windows.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <Common/UefiBaseTypes.h>
28
29 #include "ParseInf.h"
30 #include "EfiUtilityMsgs.h"
31 #include "CommonLib.h"
32
33 //
34 // Utility Name
35 //
36 #define UTILITY_NAME "GenBootSector"
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 INT
54 GetDrvNumOffset (
55 IN VOID *BootSector
56 );
57
58 typedef enum {
59 PatchTypeUnknown,
60 PatchTypeFloppy,
61 PatchTypeIde,
62 PatchTypeUsb,
63 PatchTypeFileImage // input and output are all file image, patching action is same as PatchTypeFloppy
64 } PATCH_TYPE;
65
66 typedef enum {
67 PathUnknown,
68 PathFile,
69 PathFloppy,
70 PathUsb,
71 PathIde
72 } PATH_TYPE;
73
74 typedef enum {
75 ErrorSuccess,
76 ErrorFileCreate,
77 ErrorFileReadWrite,
78 ErrorNoMbr,
79 ErrorFatType,
80 ErrorPath,
81 } ERROR_STATUS;
82
83 CHAR *ErrorStatusDesc[] = {
84 "Success",
85 "Failed to create files",
86 "Failed to read/write files",
87 "No MBR exists",
88 "Failed to detect Fat type",
89 "Inavlid path"
90 };
91
92 typedef struct _DRIVE_TYPE_DESC {
93 UINT Type;
94 CHAR *Description;
95 } DRIVE_TYPE_DESC;
96
97 #define DRIVE_TYPE_ITEM(x) {x, #x}
98 DRIVE_TYPE_DESC DriveTypeDesc[] = {
99 DRIVE_TYPE_ITEM (DRIVE_UNKNOWN),
100 DRIVE_TYPE_ITEM (DRIVE_NO_ROOT_DIR),
101 DRIVE_TYPE_ITEM (DRIVE_REMOVABLE),
102 DRIVE_TYPE_ITEM (DRIVE_FIXED),
103 DRIVE_TYPE_ITEM (DRIVE_REMOTE),
104 DRIVE_TYPE_ITEM (DRIVE_CDROM),
105 DRIVE_TYPE_ITEM (DRIVE_RAMDISK),
106 (UINT) -1, NULL
107 };
108
109 typedef struct _DRIVE_INFO {
110 CHAR VolumeLetter;
111 DRIVE_TYPE_DESC *DriveType;
112 UINT DiskNumber;
113 } DRIVE_INFO;
114
115 typedef struct _PATH_INFO {
116 CHAR *Path;
117 CHAR PhysicalPath[260];
118 PATH_TYPE Type;
119 BOOL Input;
120 } PATH_INFO;
121
122 #define BOOT_SECTOR_LBA_OFFSET 0x1FA
123
124 #define IsLetter(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z'))
125
126 BOOL
127 GetDriveInfo (
128 CHAR VolumeLetter,
129 DRIVE_INFO *DriveInfo
130 )
131 /*++
132 Routine Description:
133 Get drive information including disk number and drive type,
134 where disknumber is useful for reading/writing disk raw data.
135 NOTE: Floppy disk doesn't have disk number but it doesn't matter because
136 we can reading/writing floppy disk without disk number.
137
138 Arguments:
139 VolumeLetter : volume letter, e.g.: C for C:, A for A:
140 DriveInfo : pointer to DRIVE_INFO structure receiving drive information.
141
142 Return:
143 TRUE : successful
144 FALSE : failed
145 --*/
146 {
147 HANDLE VolumeHandle;
148 STORAGE_DEVICE_NUMBER StorageDeviceNumber;
149 DWORD BytesReturned;
150 BOOL Success;
151 UINT DriveType;
152 UINT Index;
153
154 CHAR RootPath[] = "X:\\"; // "X:\" -> for GetDriveType
155 CHAR VolumeAccessPath[] = "\\\\.\\X:"; // "\\.\X:" -> to open the volume
156
157 RootPath[0] = VolumeAccessPath[4] = VolumeLetter;
158 DriveType = GetDriveType(RootPath);
159 if (DriveType != DRIVE_REMOVABLE && DriveType != DRIVE_FIXED) {
160 return FALSE;
161 }
162
163 DriveInfo->VolumeLetter = VolumeLetter;
164 VolumeHandle = CreateFile (
165 VolumeAccessPath,
166 0,
167 FILE_SHARE_READ | FILE_SHARE_WRITE,
168 NULL,
169 OPEN_EXISTING,
170 0,
171 NULL
172 );
173 if (VolumeHandle == INVALID_HANDLE_VALUE) {
174 fprintf (
175 stderr,
176 "error E0005: CreateFile failed: Volume = %s, LastError = 0x%x\n",
177 VolumeAccessPath,
178 GetLastError ()
179 );
180 return FALSE;
181 }
182
183 //
184 // Get Disk Number. It should fail when operating on floppy. That's ok
185 // because Disk Number is only needed when operating on Hard or USB disk.
186 //
187 // To direct write to disk:
188 // for USB and HD: use path = \\.\PHYSICALDRIVEx, where x is Disk Number
189 // for floppy: use path = \\.\X:, where X can be A or B
190 //
191 Success = DeviceIoControl(
192 VolumeHandle,
193 IOCTL_STORAGE_GET_DEVICE_NUMBER,
194 NULL,
195 0,
196 &StorageDeviceNumber,
197 sizeof(StorageDeviceNumber),
198 &BytesReturned,
199 NULL
200 );
201 //
202 // DeviceIoControl should fail if Volume is floppy or network drive.
203 //
204 if (!Success) {
205 DriveInfo->DiskNumber = (UINT) -1;
206 } else if (StorageDeviceNumber.DeviceType != FILE_DEVICE_DISK) {
207 //
208 // Only care about the disk.
209 //
210 return FALSE;
211 } else{
212 DriveInfo->DiskNumber = StorageDeviceNumber.DeviceNumber;
213 }
214 CloseHandle(VolumeHandle);
215
216 //
217 // Fill in the type string
218 //
219 DriveInfo->DriveType = NULL;
220 for (Index = 0; DriveTypeDesc[Index].Description != NULL; Index ++) {
221 if (DriveType == DriveTypeDesc[Index].Type) {
222 DriveInfo->DriveType = &DriveTypeDesc[Index];
223 break;
224 }
225 }
226
227 if (DriveInfo->DriveType == NULL) {
228 //
229 // Should have a type.
230 //
231 fprintf (stderr, "error E3005: Fatal Error!!!\n");
232 return FALSE;
233 }
234 return TRUE;
235 }
236
237 VOID
238 ListDrive (
239 VOID
240 )
241 /*++
242 Routine Description:
243 List every drive in current system and their information.
244
245 --*/
246 {
247 UINT Index;
248 DRIVE_INFO DriveInfo;
249
250 UINT Mask = GetLogicalDrives();
251
252 for (Index = 0; Index < MAX_DRIVE; Index++) {
253 if (((Mask >> Index) & 0x1) == 1) {
254 if (GetDriveInfo ('A' + (CHAR) Index, &DriveInfo)) {
255 if (Index < 2) {
256 // Floppy will occupy 'A' and 'B'
257 fprintf (
258 stdout,
259 "%c: - Type: %s\n",
260 DriveInfo.VolumeLetter,
261 DriveInfo.DriveType->Description
262 );
263 } else {
264 fprintf (
265 stdout,
266 "%c: - DiskNum: %u, Type: %s\n",
267 DriveInfo.VolumeLetter,
268 (unsigned) DriveInfo.DiskNumber,
269 DriveInfo.DriveType->Description
270 );
271 }
272 }
273 }
274 }
275
276 }
277
278 INT
279 GetBootSectorOffset (
280 HANDLE DiskHandle,
281 PATH_INFO *PathInfo
282 )
283 /*++
284 Description:
285 Get the offset of boot sector.
286 For non-MBR disk, offset is just 0
287 for disk with MBR, offset needs to be caculated by parsing MBR
288
289 NOTE: if no one is active, we will patch MBR to select first partition as active.
290
291 Arguments:
292 DiskHandle : HANDLE of disk
293 PathInfo : PATH_INFO structure.
294 WriteToDisk : TRUE indicates writing
295
296 Return:
297 -1 : failed
298 o.w. : Offset to boot sector
299 --*/
300 {
301 BYTE DiskPartition[0x200];
302 DWORD BytesReturn;
303 DWORD DbrOffset;
304 DWORD Index;
305 BOOL HasMbr;
306
307 DbrOffset = 0;
308 HasMbr = FALSE;
309
310 SetFilePointer(DiskHandle, 0, NULL, FILE_BEGIN);
311 if (!ReadFile (DiskHandle, DiskPartition, 0x200, &BytesReturn, NULL)) {
312 return -1;
313 }
314
315 //
316 // Check Signature, Jmp, and Boot Indicator.
317 // if all pass, we assume MBR found.
318 //
319
320 // Check Signature: 55AA
321 if ((DiskPartition[0x1FE] == 0x55) && (DiskPartition[0x1FF] == 0xAA)) {
322 // Check Jmp: (EB ?? 90) or (E9 ?? ??)
323 if (((DiskPartition[0] != 0xEB) || (DiskPartition[2] != 0x90)) &&
324 (DiskPartition[0] != 0xE9)) {
325 // Check Boot Indicator: 0x00 or 0x80
326 // Boot Indicator is the first byte of Partition Entry
327 HasMbr = TRUE;
328 for (Index = 0; Index < PARTITION_ENTRY_NUM; ++Index) {
329 if ((DiskPartition[PARTITION_TABLE_OFFSET + Index * SIZE_OF_PARTITION_ENTRY] & 0x7F) != 0) {
330 HasMbr = FALSE;
331 break;
332 }
333 }
334 }
335 }
336
337 if (HasMbr) {
338 //
339 // Skip MBR
340 //
341 for (Index = 0; Index < PARTITION_ENTRY_NUM; Index++) {
342 //
343 // Found Boot Indicator.
344 //
345 if (DiskPartition[PARTITION_TABLE_OFFSET + (Index * SIZE_OF_PARTITION_ENTRY)] == 0x80) {
346 DbrOffset = *(DWORD *)&DiskPartition[PARTITION_TABLE_OFFSET + (Index * SIZE_OF_PARTITION_ENTRY) + PARTITION_ENTRY_STARTLBA_OFFSET];
347 break;
348 }
349 }
350 //
351 // If no boot indicator, we manually select 1st partition, and patch MBR.
352 //
353 if (Index == PARTITION_ENTRY_NUM) {
354 DbrOffset = *(DWORD *)&DiskPartition[PARTITION_TABLE_OFFSET + PARTITION_ENTRY_STARTLBA_OFFSET];
355 if (!PathInfo->Input && (PathInfo->Type == PathUsb)) {
356 SetFilePointer(DiskHandle, 0, NULL, FILE_BEGIN);
357 DiskPartition[PARTITION_TABLE_OFFSET] = 0x80;
358 WriteFile (DiskHandle, DiskPartition, 0x200, &BytesReturn, NULL);
359 }
360 }
361 }
362
363 return DbrOffset;
364 }
365
366 /**
367 * Get window file handle for input/ouput disk/file.
368 *
369 * @param PathInfo
370 * @param ProcessMbr
371 * @param FileHandle
372 *
373 * @return ERROR_STATUS
374 */
375 ERROR_STATUS
376 GetFileHandle (
377 PATH_INFO *PathInfo,
378 BOOL ProcessMbr,
379 HANDLE *FileHandle,
380 DWORD *DbrOffset
381 )
382 {
383 DWORD OpenFlag;
384
385 OpenFlag = OPEN_ALWAYS;
386 if (PathInfo->Input || PathInfo->Type != PathFile) {
387 OpenFlag = OPEN_EXISTING;
388 }
389
390 *FileHandle = CreateFile(
391 PathInfo->PhysicalPath,
392 GENERIC_READ | GENERIC_WRITE,
393 FILE_SHARE_READ,
394 NULL,
395 OpenFlag,
396 FILE_ATTRIBUTE_NORMAL,
397 NULL
398 );
399 if (*FileHandle == INVALID_HANDLE_VALUE) {
400 return ErrorFileCreate;
401 }
402
403 if ((PathInfo->Type == PathIde) || (PathInfo->Type == PathUsb)){
404 *DbrOffset = GetBootSectorOffset (*FileHandle, PathInfo);
405 if (!ProcessMbr) {
406 //
407 // 1. Process boot sector, set file pointer to the beginning of boot sector
408 //
409 SetFilePointer (*FileHandle, *DbrOffset * 0x200, NULL, FILE_BEGIN);
410 } else if(*DbrOffset == 0) {
411 //
412 // If user want to process Mbr, but no Mbr exists, simply return FALSE
413 //
414 return ErrorNoMbr;
415 } else {
416 //
417 // 2. Process MBR, set file pointer to 0
418 //
419 SetFilePointer (*FileHandle, 0, NULL, FILE_BEGIN);
420 }
421 }
422
423 return ErrorSuccess;
424 }
425
426 /**
427 Writing or reading boot sector or MBR according to the argument.
428
429 @param InputInfo PATH_INFO instance for input path
430 @param OutputInfo PATH_INFO instance for output path
431 @param ProcessMbr TRUE is to process MBR, otherwise, processing boot sector
432
433 @return ERROR_STATUS
434 **/
435 ERROR_STATUS
436 ProcessBsOrMbr (
437 PATH_INFO *InputInfo,
438 PATH_INFO *OutputInfo,
439 BOOL ProcessMbr
440 )
441 {
442 BYTE DiskPartition[0x200] = {0};
443 BYTE DiskPartitionBackup[0x200] = {0};
444 DWORD BytesReturn;
445 INT DrvNumOffset;
446 HANDLE InputHandle;
447 HANDLE OutputHandle;
448 ERROR_STATUS Status;
449 DWORD InputDbrOffset;
450 DWORD OutputDbrOffset;
451
452 //
453 // Create file Handle and move file Pointer is pointed to beginning of Mbr or Dbr
454 //
455 Status = GetFileHandle(InputInfo, ProcessMbr, &InputHandle, &InputDbrOffset);
456 if (Status != ErrorSuccess) {
457 return Status;
458 }
459
460 //
461 // Create file Handle and move file Pointer is pointed to beginning of Mbr or Dbr
462 //
463 Status = GetFileHandle(OutputInfo, ProcessMbr, &OutputHandle, &OutputDbrOffset);
464 if (Status != ErrorSuccess) {
465 return Status;
466 }
467
468 //
469 // Read boot sector from source disk/file
470 //
471 if (!ReadFile (InputHandle, DiskPartition, 0x200, &BytesReturn, NULL)) {
472 return ErrorFileReadWrite;
473 }
474
475 if (InputInfo->Type == PathUsb) {
476 // Manually set BS_DrvNum to 0x80 as window's format.exe has a bug which will clear this field discarding USB disk's MBR.
477 // offset of BS_DrvNum is 0x24 for FAT12/16
478 // 0x40 for FAT32
479 //
480 DrvNumOffset = GetDrvNumOffset (DiskPartition);
481 if (DrvNumOffset == -1) {
482 return ErrorFatType;
483 }
484 //
485 // Some legacy BIOS require 0x80 discarding MBR.
486 // Question left here: is it needed to check Mbr before set 0x80?
487 //
488 DiskPartition[DrvNumOffset] = ((InputDbrOffset > 0) ? 0x80 : 0);
489 }
490
491 if (InputInfo->Type == PathIde) {
492 //
493 // Patch LBAOffsetForBootSector
494 //
495 *(DWORD *)&DiskPartition [BOOT_SECTOR_LBA_OFFSET] = InputDbrOffset;
496 }
497
498 if (OutputInfo->Type != PathFile) {
499 if (ProcessMbr) {
500 //
501 // Use original partition table
502 //
503 if (!ReadFile (OutputHandle, DiskPartitionBackup, 0x200, &BytesReturn, NULL)) {
504 return ErrorFileReadWrite;
505 }
506 memcpy (DiskPartition + 0x1BE, DiskPartitionBackup + 0x1BE, 0x40);
507 SetFilePointer (OutputHandle, 0, NULL, FILE_BEGIN);
508
509 }
510 }
511
512 //
513 // Write boot sector to taget disk/file
514 //
515 if (!WriteFile (OutputHandle, DiskPartition, 0x200, &BytesReturn, NULL)) {
516 return ErrorFileReadWrite;
517 }
518
519 CloseHandle (InputHandle);
520 CloseHandle (OutputHandle);
521
522 return ErrorSuccess;
523 }
524
525 void
526 Version (
527 void
528 )
529 /*++
530
531 Routine Description:
532
533 Displays the standard utility information to SDTOUT
534
535 Arguments:
536
537 None
538
539 Returns:
540
541 None
542
543 --*/
544 {
545 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);
546 printf ("Copyright (c) 2009 - 2010 Intel Corporation. All rights reserved.\n");
547 }
548
549 VOID
550 PrintUsage (
551 void
552 )
553 {
554 Version();
555 printf ("\nUsage: \n\
556 GenBootSector\n\
557 [-l, --list list disks]\n\
558 [-i, --input Filename]\n\
559 [-o, --output Filename]\n\
560 [-m, --mbr process the MBR also]\n\
561 [-v, --verbose]\n\
562 [--version]\n\
563 [-q, --quiet disable all messages except fatal errors]\n\
564 [-d, --debug[#]\n\
565 [-h, --help]\n");
566
567 }
568
569 /**
570 Get path information, including physical path for windows platform.
571
572 @param PathInfo Point to PATH_INFO structure.
573
574 @return whether path is valid.
575 **/
576 ERROR_STATUS
577 GetPathInfo (
578 PATH_INFO *PathInfo
579 )
580 {
581 DRIVE_INFO DriveInfo;
582 CHAR VolumeLetter;
583 CHAR DiskPathTemplate[] = "\\\\.\\PHYSICALDRIVE%u";
584 CHAR FloppyPathTemplate[] = "\\\\.\\%c:";
585 FILE *f;
586
587 //
588 // If path is disk path
589 //
590 if (IsLetter(PathInfo->Path[0]) && (PathInfo->Path[1] == ':') && (PathInfo->Path[2] == '\0')) {
591 VolumeLetter = PathInfo->Path[0];
592 if ((VolumeLetter == 'A') || (VolumeLetter == 'a') ||
593 (VolumeLetter == 'B') || (VolumeLetter == 'b')) {
594 PathInfo->Type = PathFloppy;
595 sprintf (PathInfo->PhysicalPath, FloppyPathTemplate, VolumeLetter);
596 return ErrorSuccess;
597 }
598
599 if (!GetDriveInfo(VolumeLetter, &DriveInfo)) {
600 fprintf (stderr, "ERROR: GetDriveInfo - 0x%x\n", GetLastError ());
601 return ErrorPath;
602 }
603
604 if (!PathInfo->Input && (DriveInfo.DriveType->Type == DRIVE_FIXED)) {
605 fprintf (stderr, "ERROR: Could patch own IDE disk!\n");
606 return ErrorPath;
607 }
608
609 sprintf(PathInfo->PhysicalPath, DiskPathTemplate, DriveInfo.DiskNumber);
610 if (DriveInfo.DriveType->Type == DRIVE_REMOVABLE) {
611 PathInfo->Type = PathUsb;
612 } else if (DriveInfo.DriveType->Type == DRIVE_FIXED) {
613 PathInfo->Type = PathIde;
614 } else {
615 fprintf (stderr, "ERROR, Invalid disk path - %s", PathInfo->Path);
616 return ErrorPath;
617 }
618
619 return ErrorSuccess;
620 }
621
622 PathInfo->Type = PathFile;
623 if (PathInfo->Input) {
624 //
625 // If path is file path, check whether file is valid.
626 //
627 f = fopen (PathInfo->Path, "r");
628 if (f == NULL) {
629 fprintf (stderr, "error E2003: File was not provided!\n");
630 return ErrorPath;
631 }
632 }
633 PathInfo->Type = PathFile;
634 strcpy(PathInfo->PhysicalPath, PathInfo->Path);
635
636 return ErrorSuccess;
637 }
638
639 INT
640 main (
641 INT argc,
642 CHAR *argv[]
643 )
644 {
645 CHAR8 *AppName;
646 INTN Index;
647 BOOLEAN ProcessMbr;
648 ERROR_STATUS Status;
649 EFI_STATUS EfiStatus;
650 PATH_INFO InputPathInfo = {0};
651 PATH_INFO OutputPathInfo = {0};
652 UINT64 LogLevel;
653
654 SetUtilityName (UTILITY_NAME);
655
656 AppName = *argv;
657 argv ++;
658 argc --;
659
660 ProcessMbr = FALSE;
661
662 if (argc == 0) {
663 PrintUsage();
664 return 0;
665 }
666
667 //
668 // Parse command line
669 //
670 for (Index = 0; Index < argc; Index ++) {
671 if ((stricmp (argv[Index], "-l") == 0) || (stricmp (argv[Index], "--list") == 0)) {
672 ListDrive ();
673 return 0;
674 }
675
676 if ((stricmp (argv[Index], "-m") == 0) || (stricmp (argv[Index], "--mbr") == 0)) {
677 ProcessMbr = TRUE;
678 continue;
679 }
680
681 if ((stricmp (argv[Index], "-i") == 0) || (stricmp (argv[Index], "--input") == 0)) {
682 InputPathInfo.Path = argv[Index + 1];
683 InputPathInfo.Input = TRUE;
684 if (InputPathInfo.Path == NULL) {
685 Error (NULL, 0, 1003, "Invalid option value", "Input file name can't be NULL");
686 return 1;
687 }
688 if (InputPathInfo.Path[0] == '-') {
689 Error (NULL, 0, 1003, "Invalid option value", "Input file is missing");
690 return 1;
691 }
692 ++Index;
693 continue;
694 }
695
696 if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {
697 OutputPathInfo.Path = argv[Index + 1];
698 OutputPathInfo.Input = FALSE;
699 if (OutputPathInfo.Path == NULL) {
700 Error (NULL, 0, 1003, "Invalid option value", "Output file name can't be NULL");
701 return 1;
702 }
703 if (OutputPathInfo.Path[0] == '-') {
704 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing");
705 return 1;
706 }
707 ++Index;
708 continue;
709 }
710
711 if ((stricmp (argv[Index], "-h") == 0) || (stricmp (argv[Index], "--help") == 0)) {
712 PrintUsage ();
713 return 0;
714 }
715
716 if (stricmp (argv[Index], "--version") == 0) {
717 Version ();
718 return 0;
719 }
720
721 if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {
722 continue;
723 }
724
725 if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {
726 continue;
727 }
728
729 if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {
730 EfiStatus = AsciiStringToUint64 (argv[Index + 1], FALSE, &LogLevel);
731 if (EFI_ERROR (EfiStatus)) {
732 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);
733 return 1;
734 }
735 if (LogLevel > 9) {
736 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel);
737 return 1;
738 }
739 SetPrintLevel (LogLevel);
740 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[Index + 1]);
741 ++Index;
742 continue;
743 }
744
745 //
746 // Don't recognize the parameter.
747 //
748 Error (NULL, 0, 1000, "Unknown option", "%s", argv[Index]);
749 return 1;
750 }
751
752 if (InputPathInfo.Path == NULL) {
753 Error (NULL, 0, 1001, "Missing options", "Input file is missing");
754 return 1;
755 }
756
757 if (OutputPathInfo.Path == NULL) {
758 Error (NULL, 0, 1001, "Missing options", "Output file is missing");
759 return 1;
760 }
761
762 if (GetPathInfo(&InputPathInfo) != ErrorSuccess) {
763 Error (NULL, 0, 1003, "Invalid option value", "Input file can't be found.");
764 return 1;
765 }
766
767 if (GetPathInfo(&OutputPathInfo) != ErrorSuccess) {
768 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be found.");
769 return 1;
770 }
771
772 //
773 // Process DBR (Patch or Read)
774 //
775 Status = ProcessBsOrMbr (&InputPathInfo, &OutputPathInfo, ProcessMbr);
776
777 if (Status == ErrorSuccess) {
778 fprintf (
779 stdout,
780 "%s %s: successful!\n",
781 (OutputPathInfo.Type != PathFile) ? "Write" : "Read",
782 ProcessMbr ? "MBR" : "DBR"
783 );
784 return 0;
785 } else {
786 fprintf (
787 stderr,
788 "%s: %s %s: failed - %s (LastError: 0x%x)!\n",
789 (Status == ErrorNoMbr) ? "WARNING" : "ERROR",
790 (OutputPathInfo.Type != PathFile) ? "Write" : "Read",
791 ProcessMbr ? "MBR" : "DBR",
792 ErrorStatusDesc[Status],
793 GetLastError ()
794 );
795 return 1;
796 }
797 }