+++ /dev/null
-/** @file\r
-Reading/writing MBR/DBR.\r
- NOTE:\r
- If we write MBR to disk, we just update the MBR code and the partition table wouldn't be over written.\r
- If we process DBR, we will patch MBR to set first partition active if no active partition exists.\r
-\r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "CommonLib.h"\r
-#include <errno.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <Common/UefiBaseTypes.h>\r
-\r
-#include "ParseInf.h"\r
-#include "EfiUtilityMsgs.h"\r
-\r
-//\r
-// Utility Name\r
-//\r
-#define UTILITY_NAME "GnuGenBootSector"\r
-\r
-//\r
-// Utility version information\r
-//\r
-#define UTILITY_MAJOR_VERSION 0\r
-#define UTILITY_MINOR_VERSION 1\r
-\r
-#define MAX_DRIVE 26\r
-#define PARTITION_TABLE_OFFSET 0x1BE\r
-\r
-#define SIZE_OF_PARTITION_ENTRY 0x10\r
-\r
-#define PARTITION_ENTRY_STARTLBA_OFFSET 8\r
-\r
-#define PARTITION_ENTRY_NUM 4\r
-\r
-#define DRIVE_UNKNOWN 0\r
-#define DRIVE_NO_ROOT_DIR 1\r
-#define DRIVE_REMOVABLE 2\r
-#define DRIVE_FIXED 3\r
-#define DRIVE_REMOTE 4\r
-#define DRIVE_CDROM 5\r
-#define DRIVE_RAMDISK 6\r
-\r
-typedef struct _DRIVE_TYPE_DESC {\r
- UINTN Type;\r
- CHAR8 *Description;\r
-} DRIVE_TYPE_DESC;\r
-\r
-#define DRIVE_TYPE_ITEM(x) {x, #x}\r
-\r
-DRIVE_TYPE_DESC DriveTypeDesc[] = {\r
- DRIVE_TYPE_ITEM (DRIVE_UNKNOWN),\r
- DRIVE_TYPE_ITEM (DRIVE_NO_ROOT_DIR),\r
- DRIVE_TYPE_ITEM (DRIVE_REMOVABLE),\r
- DRIVE_TYPE_ITEM (DRIVE_FIXED),\r
- DRIVE_TYPE_ITEM (DRIVE_REMOTE),\r
- DRIVE_TYPE_ITEM (DRIVE_CDROM),\r
- DRIVE_TYPE_ITEM (DRIVE_RAMDISK),\r
- {(UINTN) -1, NULL}\r
-};\r
-\r
-typedef struct _DRIVE_INFO {\r
- CHAR8 VolumeLetter;\r
- DRIVE_TYPE_DESC *DriveType;\r
- UINTN DiskNumber;\r
-} DRIVE_INFO;\r
-\r
-typedef enum {\r
- PathUnknown,\r
- PathFile,\r
- PathFloppy,\r
- PathUsb,\r
- PathIde\r
-} PATH_TYPE;\r
-\r
-typedef struct _PATH_INFO {\r
- CHAR8 *Path;\r
- CHAR8 PhysicalPath[260];\r
- PATH_TYPE Type;\r
- BOOLEAN Input;\r
-} PATH_INFO;\r
-\r
-typedef enum {\r
- ErrorSuccess,\r
- ErrorFileCreate,\r
- ErrorFileReadWrite,\r
- ErrorNoMbr,\r
- ErrorFatType,\r
- ErrorPath,\r
-} ERROR_STATUS;\r
-\r
-CHAR8 *ErrorStatusDesc[] = {\r
- "Success",\r
- "Failed to create files",\r
- "Failed to read/write files",\r
- "No MBR exists",\r
- "Failed to detect Fat type",\r
- "Inavlid path"\r
-};\r
-\r
-\r
-//UnSupported Windows API functions.\r
-UINTN GetLogicalDrives(void) { return 1; }\r
-\r
-\r
-\r
-/**\r
- Get path information, including physical path for Linux platform.\r
-\r
- @param PathInfo Point to PATH_INFO structure.\r
-\r
- @return whether path is valid.\r
-**/\r
-ERROR_STATUS\r
-GetPathInfo (\r
- PATH_INFO *PathInfo\r
- )\r
-{\r
- FILE *f;\r
-\r
- if (strncmp(PathInfo->Path, "/dev/", 5) == 0) {\r
- //\r
- // Process disk path here.\r
- //\r
-\r
- // Process floppy disk\r
- if (PathInfo->Path[5] == 'f' && PathInfo->Path[6] == 'd' && PathInfo->Path[8] == '\0') {\r
- PathInfo->Type = PathFloppy;\r
- strcpy (PathInfo->PhysicalPath, PathInfo->Path);\r
-\r
- return ErrorSuccess;\r
- } else {\r
- // Other disk types is not supported yet.\r
- fprintf (stderr, "ERROR: It's not a floppy disk!\n");\r
- return ErrorPath;\r
- }\r
-\r
- // Try to open the device.\r
- f = fopen (LongFilePath (PathInfo->Path),"r");\r
- if (f == NULL) {\r
- printf ("error :open device failed!\n");\r
- return ErrorPath;\r
- }\r
- fclose (f);\r
- return ErrorSuccess;\r
- }\r
-\r
- // Process file path here.\r
- PathInfo->Type = PathFile;\r
- if (PathInfo->Input) {\r
- // If path is file path, check whether file is valid.\r
- printf("Path = %s\n",PathInfo->Path);\r
- f = fopen (LongFilePath (PathInfo->Path), "r");\r
- if (f == NULL) {\r
- fprintf (stderr, "Test error E2003: File was not provided!\n");\r
- return ErrorPath;\r
- }\r
- fclose (f);\r
- }\r
-\r
- strcpy(PathInfo->PhysicalPath, PathInfo->Path);\r
- return ErrorSuccess;\r
-\r
-}\r
-\r
-VOID\r
-ListDrive (\r
- VOID\r
- )\r
-{\r
- printf("-l or -list not supported!\n");\r
-}\r
-\r
-/**\r
- Writing or reading boot sector or MBR according to the argument.\r
-\r
- @param InputInfo PATH_INFO instance for input path\r
- @param OutputInfo PATH_INFO instance for output path\r
- @param ProcessMbr TRUE is to process MBR, otherwise, processing boot sector\r
-\r
- @return ERROR_STATUS\r
- **/\r
-ERROR_STATUS\r
-ProcessBsOrMbr (\r
- PATH_INFO *InputInfo,\r
- PATH_INFO *OutputInfo,\r
- BOOLEAN ProcessMbr\r
- )\r
-{\r
- CHAR8 FirstSector[0x200] = {0};\r
- CHAR8 FirstSectorBackup[0x200] = {0};\r
-\r
- FILE *InputFile;\r
- FILE *OutputFile;\r
-\r
-\r
- InputFile = fopen (LongFilePath (InputInfo->PhysicalPath), "r");\r
- if (InputFile == NULL) {\r
- return ErrorFileReadWrite;\r
- }\r
-\r
- if (0x200 != fread(FirstSector, 1, 0x200, InputFile)) {\r
- fclose(InputFile);\r
- return ErrorFileReadWrite;\r
- }\r
-\r
- fclose(InputFile);\r
-\r
- //Not support USB and IDE.\r
- if (InputInfo->Type == PathUsb) {\r
- printf("USB has not been supported yet!");\r
- return ErrorSuccess;\r
- }\r
-\r
- if (InputInfo->Type == PathIde) {\r
- printf("IDE has not been supported yet!");\r
- return ErrorSuccess;\r
- }\r
-\r
- //Process Floppy Disk\r
- OutputFile = fopen (LongFilePath (OutputInfo->PhysicalPath), "r+");\r
- if (OutputFile == NULL) {\r
- OutputFile = fopen (LongFilePath (OutputInfo->PhysicalPath), "w");\r
- if (OutputFile == NULL) {\r
- return ErrorFileReadWrite;\r
- }\r
- }\r
-\r
- if (OutputInfo->Type != PathFile) {\r
- if (ProcessMbr) {\r
- //\r
- // Use original partition table\r
- //\r
- if (0x200 != fread (FirstSectorBackup, 1, 0x200, OutputFile)) {\r
- fclose(OutputFile);\r
- return ErrorFileReadWrite;\r
- }\r
- memcpy (FirstSector + 0x1BE, FirstSectorBackup + 0x1BE, 0x40);\r
- }\r
- }\r
- if(0x200 != fwrite(FirstSector, 1, 0x200, OutputFile)) {\r
- fclose(OutputFile);\r
- return ErrorFileReadWrite;\r
- }\r
-\r
- fclose(OutputFile);\r
- return ErrorSuccess;\r
-}\r
-\r
-\r
-/**\r
-\r
- Displays the standard utility information to SDTOUT\r
-\r
-**/\r
-VOID\r
-Version (\r
- VOID\r
- )\r
-{\r
- 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
- printf ("Copyright (c) 2007-2014 Intel Corporation. All rights reserved.\n");\r
-}\r
-\r
-\r
-VOID\r
-PrintUsage (\r
- VOID\r
- )\r
-{\r
- Version();\r
- printf ("\nUsage: \n\\r
- GenBootSector\n\\r
- [-l, --list list disks]\n\\r
- [-i, --input Filename]\n\\r
- [-o, --output Filename]\n\\r
- [-m, --mbr process the MBR also]\n\\r
- [-v, --verbose]\n\\r
- [--version]\n\\r
- [-q, --quiet disable all messages except fatal errors]\n\\r
- [-d, --debug[#]\n\\r
- [-h, --help]\n");\r
-}\r
-\r
-int\r
-main (\r
- int argc,\r
- char *argv[]\r
- )\r
-{\r
- INTN Index;\r
- BOOLEAN ProcessMbr;\r
- ERROR_STATUS Status;\r
- EFI_STATUS EfiStatus;\r
- PATH_INFO InputPathInfo;\r
- PATH_INFO OutputPathInfo;\r
- UINT64 LogLevel;\r
-\r
- SetUtilityName (UTILITY_NAME);\r
-\r
- ZeroMem(&InputPathInfo, sizeof(PATH_INFO));\r
- ZeroMem(&OutputPathInfo, sizeof(PATH_INFO));\r
-\r
- argv ++;\r
- argc --;\r
-\r
- ProcessMbr = FALSE;\r
-\r
- if (argc == 0) {\r
- PrintUsage();\r
- return 0;\r
- }\r
-\r
- //\r
- // Parse command line\r
- //\r
- for (Index = 0; Index < argc; Index ++) {\r
- if ((stricmp (argv[Index], "-l") == 0) || (stricmp (argv[Index], "--list") == 0)) {\r
- ListDrive ();\r
- return 0;\r
- }\r
-\r
- if ((stricmp (argv[Index], "-m") == 0) || (stricmp (argv[Index], "--mbr") == 0)) {\r
- ProcessMbr = TRUE;\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[Index], "-i") == 0) || (stricmp (argv[Index], "--input") == 0)) {\r
- InputPathInfo.Path = argv[Index + 1];\r
- InputPathInfo.Input = TRUE;\r
- if (InputPathInfo.Path == NULL) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Input file name can't be NULL");\r
- return 1;\r
- }\r
- if (InputPathInfo.Path[0] == '-') {\r
- Error (NULL, 0, 1003, "Invalid option value", "Input file is missing");\r
- return 1;\r
- }\r
- ++Index;\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {\r
- OutputPathInfo.Path = argv[Index + 1];\r
- OutputPathInfo.Input = FALSE;\r
- if (OutputPathInfo.Path == NULL) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Output file name can't be NULL");\r
- return 1;\r
- }\r
- if (OutputPathInfo.Path[0] == '-') {\r
- Error (NULL, 0, 1003, "Invalid option value", "Output file is missing");\r
- return 1;\r
- }\r
- ++Index;\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[Index], "-h") == 0) || (stricmp (argv[Index], "--help") == 0)) {\r
- PrintUsage ();\r
- return 0;\r
- }\r
-\r
- if (stricmp (argv[Index], "--version") == 0) {\r
- Version ();\r
- return 0;\r
- }\r
-\r
- if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {\r
- EfiStatus = AsciiStringToUint64 (argv[Index + 1], FALSE, &LogLevel);\r
- if (EFI_ERROR (EfiStatus)) {\r
- Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);\r
- return 1;\r
- }\r
- if (LogLevel > 9) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel);\r
- return 1;\r
- }\r
- SetPrintLevel (LogLevel);\r
- DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[Index + 1]);\r
- ++Index;\r
- continue;\r
- }\r
-\r
- //\r
- // Don't recognize the parameter.\r
- //\r
- Error (NULL, 0, 1000, "Unknown option", "%s", argv[Index]);\r
- return 1;\r
- }\r
-\r
- if (InputPathInfo.Path == NULL) {\r
- Error (NULL, 0, 1001, "Missing options", "Input file is missing");\r
- return 1;\r
- }\r
-\r
- if (OutputPathInfo.Path == NULL) {\r
- Error (NULL, 0, 1001, "Missing options", "Output file is missing");\r
- return 1;\r
- }\r
-\r
- if (GetPathInfo(&InputPathInfo) != ErrorSuccess) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Input file can't be found.");\r
- return 1;\r
- }\r
-\r
- if (GetPathInfo(&OutputPathInfo) != ErrorSuccess) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Output file can't be found.");\r
- return 1;\r
- }\r
-\r
- //\r
- // Process DBR (Patch or Read)\r
- //\r
- Status = ProcessBsOrMbr (&InputPathInfo, &OutputPathInfo, ProcessMbr);\r
-\r
- if (Status == ErrorSuccess) {\r
- fprintf (\r
- stdout,\r
- "%s %s: successful!\n",\r
- (OutputPathInfo.Type != PathFile) ? "Write" : "Read",\r
- ProcessMbr ? "MBR" : "DBR"\r
- );\r
- return 0;\r
- } else {\r
- fprintf (\r
- stderr,\r
- "%s: %s %s: failed - %s (LastError: 0x%x)!\n",\r
- (Status == ErrorNoMbr) ? "WARNING" : "ERROR",\r
- (OutputPathInfo.Type != PathFile) ? "Write" : "Read",\r
- ProcessMbr ? "MBR" : "DBR",\r
- ErrorStatusDesc[Status],\r
- errno\r
- );\r
- return 1;\r
- }\r
-}\r