]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/BootSectImage/bootsectimage.c
Check In tool source code based on Build tool project revision r1655.
[mirror_edk2.git] / BaseTools / Source / C / BootSectImage / bootsectimage.c
diff --git a/BaseTools/Source/C/BootSectImage/bootsectimage.c b/BaseTools/Source/C/BootSectImage/bootsectimage.c
new file mode 100644 (file)
index 0000000..10a5452
--- /dev/null
@@ -0,0 +1,930 @@
+/** @file\r
+\r
+Abstract:\r
+  Patch the BPB information in boot sector image file.\r
+  Patch the MBR code in MBR image file.\r
+\r
+Copyright 2006 - 2008, Intel Corporation                                                         \r
+All rights reserved. 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 <stdio.h>\r
+#include <string.h>\r
+#include "fat.h"\r
+#include "mbr.h"\r
+#include "EfiUtilityMsgs.h"\r
+\r
+#define DEBUG_WARN  0x1\r
+#define DEBUG_ERROR 0x2\r
+\r
+//\r
+// Utility Name\r
+//\r
+#define UTILITY_NAME  "BootSectImage"\r
+\r
+//\r
+// Utility version information\r
+//\r
+#define UTILITY_MAJOR_VERSION 0\r
+#define UTILITY_MINOR_VERSION 1\r
+\r
+void\r
+Version (\r
+  void\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  printf ("%s v%d.%d - Utility to break a file into two pieces at the specified offset.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
+  printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");\r
+}\r
+\r
+void\r
+Usage (\r
+  void\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  Version();\r
+  printf ("\nUsage: \n\\r
+   BootSectImage\n\\r
+     [-f, --force force patch even if the FAT type of SrcImage and DstImage mismatch]\n\\r
+     [-m, --mbr process MBR instead of boot sector]\n\\r
+     [-p, --parse parse SrcImageFile]\n\\r
+     [-o, --output DstImage]\n\\r
+     [-g, --patch patch DstImage using data from SrcImageFile]\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
+     [SrcImageFile]\n");\r
+}\r
+\r
+int WriteToFile (\r
+  void *BootSector, \r
+  char *FileName\r
+  )\r
+/*++\r
+Routine Description:\r
+  Write 512 bytes boot sector to file.\r
+\r
+Arguments:\r
+  BootSector - point to a buffer containing 512 bytes boot sector to write\r
+  FileName   - file to write to\r
+\r
+Return:\r
+  int        - number of bytes wrote,\r
+                 512 indicates write successful\r
+                 0 indicates write failure\r
+--*/\r
+{\r
+  FILE *FileHandle;\r
+  int  result;\r
+\r
+  FileHandle = fopen (FileName, "r+b");\r
+  if (FileHandle == NULL) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Open file: %s", FileName);\r
+    return 0;\r
+  }\r
+  fseek (FileHandle, 0, SEEK_SET);\r
+\r
+  result = fwrite (BootSector, 1, 512, FileHandle);\r
+  if (result != 512) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Write file: %s", FileName);\r
+    result = 0;\r
+  }\r
+\r
+  fclose (FileHandle);\r
+  return result;\r
+}\r
+\r
+int ReadFromFile (\r
+  void *BootSector, \r
+  char *FileName\r
+  )\r
+/*++\r
+Routine Description:\r
+  Read first 512 bytes from file.\r
+\r
+Arguments:\r
+  BootSector - point to a buffer receiving the first 512 bytes data from file\r
+  FileName   - file to read from\r
+\r
+Return:\r
+  int        - number of bytes read,\r
+                 512 indicates read successful\r
+                 0 indicates read failure\r
+--*/\r
+{\r
+  FILE *FileHandle;\r
+  int  result;\r
+\r
+  FileHandle = fopen (FileName, "rb");\r
+  if (FileHandle == NULL) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E0001: Error opening file: %s", FileName);\r
+    return 0;\r
+  }\r
+\r
+  result = fread (BootSector, 1, 512, FileHandle);\r
+  if (result != 512) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E0004: Error reading file: %s", FileName);\r
+    result = 0;\r
+  }\r
+\r
+  fclose (FileHandle);\r
+  return result;\r
+}\r
+\r
+char *\r
+FatTypeToString (\r
+  IN FAT_TYPE        FatType\r
+  )\r
+/*++\r
+Routine Description:\r
+  Convert enum type of FatType to string\r
+--*/\r
+{\r
+  switch (FatType) {\r
+  case FatTypeFat12:\r
+    return "FAT12";\r
+  case FatTypeFat16:\r
+    return "FAT16";\r
+  case FatTypeFat32:\r
+    return "FAT32";\r
+  default:\r
+    break;\r
+  }\r
+  return "FAT Unknown";\r
+}\r
+\r
+FAT_TYPE\r
+GetFatType (\r
+  IN FAT_BPB_STRUCT  *FatBpb\r
+  )\r
+/*++\r
+Routine Description:\r
+  Determine the FAT type according to BIOS Paramater Block (BPB) data\r
+\r
+Arguments:\r
+  FatBpb - BIOS Parameter Block (BPB) data, 512 Bytes\r
+\r
+Return:\r
+  FatTypeUnknown - Cannot determine the FAT type\r
+  FatTypeFat12   - FAT12\r
+  FatTypeFat16   - FAT16\r
+  FatTypeFat32   - FAT32\r
+--*/\r
+{\r
+  FAT_TYPE FatType;\r
+  UINTN    RootDirSectors;\r
+  UINTN    FATSz;\r
+  UINTN    TotSec;\r
+  UINTN    DataSec;\r
+  UINTN    CountOfClusters;\r
+  CHAR8    FilSysType[9];\r
+\r
+  FatType = FatTypeUnknown;\r
+\r
+  //\r
+  // Simple check\r
+  //\r
+  if (FatBpb->Fat12_16.Signature != FAT_BS_SIGNATURE) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - Signature Invalid - %04x, expected: %04x",\r
+        FatBpb->Fat12_16.Signature, FAT_BS_SIGNATURE);\r
+    return FatTypeUnknown;\r
+  }\r
+\r
+  //\r
+  // Check according to FAT spec\r
+  //\r
+  if ((FatBpb->Fat12_16.BS_jmpBoot[0] != FAT_BS_JMP1) &&\r
+      (FatBpb->Fat12_16.BS_jmpBoot[0] != FAT_BS_JMP2)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BS_jmpBoot - %02x, expected: %02x or %02x",\r
+        FatBpb->Fat12_16.BS_jmpBoot[0], FAT_BS_JMP1, FAT_BS_JMP2);\r
+    return FatTypeUnknown;\r
+  }\r
+\r
+  if ((FatBpb->Fat12_16.BPB_BytsPerSec != 512) &&\r
+      (FatBpb->Fat12_16.BPB_BytsPerSec != 1024) &&\r
+      (FatBpb->Fat12_16.BPB_BytsPerSec != 2048) &&\r
+      (FatBpb->Fat12_16.BPB_BytsPerSec != 4096)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_BytsPerSec - %04x, expected: %04x, %04x, %04x, or %04x",\r
+        FatBpb->Fat12_16.BPB_BytsPerSec, 512, 1024, 2048, 4096);\r
+    return FatTypeUnknown;\r
+  }\r
+  if (FatBpb->Fat12_16.BPB_BytsPerSec != 512) {\r
+    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT - BPB_BytsPerSec - %04x, expected: %04x",\r
+        FatBpb->Fat12_16.BPB_BytsPerSec, 512);\r
+  }\r
+  if ((FatBpb->Fat12_16.BPB_SecPerClus != 1) &&\r
+      (FatBpb->Fat12_16.BPB_SecPerClus != 2) &&\r
+      (FatBpb->Fat12_16.BPB_SecPerClus != 4) &&\r
+      (FatBpb->Fat12_16.BPB_SecPerClus != 8) &&\r
+      (FatBpb->Fat12_16.BPB_SecPerClus != 16) &&\r
+      (FatBpb->Fat12_16.BPB_SecPerClus != 32) &&\r
+      (FatBpb->Fat12_16.BPB_SecPerClus != 64) &&\r
+      (FatBpb->Fat12_16.BPB_SecPerClus != 128)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_SecPerClus - %02x, expected: %02x, %02x, %02x, %02x, %02x, %02x, %02x, or %02x",\r
+        FatBpb->Fat12_16.BPB_BytsPerSec, 1, 2, 4, 8, 16, 32, 64, 128);\r
+    return FatTypeUnknown;\r
+  }\r
+  if (FatBpb->Fat12_16.BPB_BytsPerSec * FatBpb->Fat12_16.BPB_SecPerClus > 32 * 1024) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_BytsPerSec * BPB_SecPerClus - %08x, expected: <= %08x",\r
+        FatBpb->Fat12_16.BPB_BytsPerSec * FatBpb->Fat12_16.BPB_SecPerClus, 32 * 1024);\r
+    return FatTypeUnknown;\r
+  }\r
+  if (FatBpb->Fat12_16.BPB_RsvdSecCnt == 0) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_RsvdSecCnt - %04x, expected: Non-Zero Value",\r
+        FatBpb->Fat12_16.BPB_RsvdSecCnt);\r
+    return FatTypeUnknown;\r
+  }\r
+  if (FatBpb->Fat12_16.BPB_NumFATs != 2) {\r
+    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT - BPB_NumFATs - %02x, expected: %02x",\r
+        FatBpb->Fat12_16.BPB_NumFATs, 2);\r
+  }\r
+  if ((FatBpb->Fat12_16.BPB_Media != 0xF0) &&\r
+      (FatBpb->Fat12_16.BPB_Media != 0xF8) &&\r
+      (FatBpb->Fat12_16.BPB_Media != 0xF9) &&\r
+      (FatBpb->Fat12_16.BPB_Media != 0xFA) &&\r
+      (FatBpb->Fat12_16.BPB_Media != 0xFB) &&\r
+      (FatBpb->Fat12_16.BPB_Media != 0xFC) &&\r
+      (FatBpb->Fat12_16.BPB_Media != 0xFD) &&\r
+      (FatBpb->Fat12_16.BPB_Media != 0xFE) &&\r
+      (FatBpb->Fat12_16.BPB_Media != 0xFF)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_Media - %02x, expected: %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, or %02x",\r
+        FatBpb->Fat12_16.BPB_Media, 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF);\r
+    return FatTypeUnknown;\r
+  }\r
+\r
+  //\r
+  // Algo in FAT spec\r
+  //\r
+  RootDirSectors = ((FatBpb->Fat12_16.BPB_RootEntCnt * sizeof(FAT_DIRECTORY_ENTRY)) +\r
+                    (FatBpb->Fat12_16.BPB_BytsPerSec - 1)) /\r
+                   FatBpb->Fat12_16.BPB_BytsPerSec;\r
+\r
+  if (FatBpb->Fat12_16.BPB_FATSz16 != 0) {\r
+    FATSz = FatBpb->Fat12_16.BPB_FATSz16;\r
+  } else {\r
+    FATSz = FatBpb->Fat32.BPB_FATSz32;\r
+  }\r
+  if (FATSz == 0) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_FATSz16, BPB_FATSz32 - 0, expected: Non-Zero Value");\r
+    return FatTypeUnknown;\r
+  }\r
+\r
+  if (FatBpb->Fat12_16.BPB_TotSec16 != 0) {\r
+    TotSec = FatBpb->Fat12_16.BPB_TotSec16;\r
+  } else {\r
+    TotSec = FatBpb->Fat12_16.BPB_TotSec32;\r
+  }\r
+  if (TotSec == 0) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_TotSec16, BPB_TotSec32 - 0, expected: Non-Zero Value");\r
+    return FatTypeUnknown;\r
+  }\r
+\r
+  DataSec = TotSec - (\r
+                      FatBpb->Fat12_16.BPB_RsvdSecCnt +\r
+                      FatBpb->Fat12_16.BPB_NumFATs * FATSz +\r
+                      RootDirSectors\r
+                     );\r
+\r
+  CountOfClusters = DataSec / FatBpb->Fat12_16.BPB_SecPerClus;\r
+\r
+  if (CountOfClusters < FAT_MAX_FAT12_CLUSTER) {\r
+    FatType = FatTypeFat12;\r
+  } else if (CountOfClusters < FAT_MAX_FAT16_CLUSTER) {\r
+    FatType = FatTypeFat16;\r
+  } else {\r
+    FatType = FatTypeFat32;\r
+  }\r
+  //\r
+  // Check according to FAT spec\r
+  //\r
+  if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) &&\r
+       (FatBpb->Fat12_16.BPB_RsvdSecCnt != 1)) {\r
+    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT12_16 - BPB_RsvdSecCnt - %04x, expected: %04x",\r
+        FatBpb->Fat12_16.BPB_RsvdSecCnt, 1);\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+       (FatBpb->Fat12_16.BPB_RsvdSecCnt != 32)) {\r
+    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_RsvdSecCnt - %04x, expected: %04x",\r
+        FatBpb->Fat12_16.BPB_RsvdSecCnt, 32);\r
+  }\r
+  if ((FatType == FatTypeFat16) &&\r
+      (FatBpb->Fat12_16.BPB_RootEntCnt != 512)) {\r
+    printf ("WARNING: FAT16: BPB_RootEntCnt - %04x, expected - %04x\n",\r
+        FatBpb->Fat12_16.BPB_RootEntCnt, 512);\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat12_16.BPB_RootEntCnt != 0)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_RootEntCnt - %04x, expected: %04x",\r
+        FatBpb->Fat12_16.BPB_RootEntCnt, 0);\r
+    return FatTypeUnknown;\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat12_16.BPB_TotSec16 != 0)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_TotSec16 - %04x, expected: %04x",\r
+        FatBpb->Fat12_16.BPB_TotSec16, 0);\r
+    return FatTypeUnknown;\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat12_16.BPB_FATSz16 != 0)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_FATSz16 - %04x, expected: %04x",\r
+        FatBpb->Fat12_16.BPB_FATSz16, 0);\r
+    return FatTypeUnknown;\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat12_16.BPB_TotSec32 == 0)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_TotSec32 - %04x, expected: Non-Zero",\r
+        FatBpb->Fat12_16.BPB_TotSec32);\r
+    return FatTypeUnknown;\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat32.BPB_FATSz32 == 0)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_FATSz32 - %08x, expected: Non-Zero",\r
+        FatBpb->Fat32.BPB_FATSz32);\r
+    return FatTypeUnknown;\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat32.BPB_FSVer != 0)) {\r
+    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_FSVer - %08x, expected: %04x",\r
+        FatBpb->Fat32.BPB_FSVer, 0);\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat32.BPB_RootClus != 2)) {\r
+    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_RootClus - %08x, expected: %04x",\r
+        FatBpb->Fat32.BPB_RootClus, 2);\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat32.BPB_FSInfo != 1)) {\r
+    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_FSInfo - %08x, expected: %04x",\r
+        FatBpb->Fat32.BPB_FSInfo, 1);\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat32.BPB_BkBootSec != 6)) {\r
+    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_BkBootSec - %08x, expected: %04x",\r
+        FatBpb->Fat32.BPB_BkBootSec, 6);\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      ((*(UINT32 *)FatBpb->Fat32.BPB_Reserved != 0) ||\r
+       (*((UINT32 *)FatBpb->Fat32.BPB_Reserved + 1) != 0) ||\r
+       (*((UINT32 *)FatBpb->Fat32.BPB_Reserved + 2) != 0))) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_Reserved - %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x, expected: 0",\r
+        FatBpb->Fat32.BPB_Reserved[0],\r
+        FatBpb->Fat32.BPB_Reserved[1],\r
+        FatBpb->Fat32.BPB_Reserved[2],\r
+        FatBpb->Fat32.BPB_Reserved[3],\r
+        FatBpb->Fat32.BPB_Reserved[4],\r
+        FatBpb->Fat32.BPB_Reserved[5],\r
+        FatBpb->Fat32.BPB_Reserved[6],\r
+        FatBpb->Fat32.BPB_Reserved[7],\r
+        FatBpb->Fat32.BPB_Reserved[8],\r
+        FatBpb->Fat32.BPB_Reserved[9],\r
+        FatBpb->Fat32.BPB_Reserved[10],\r
+        FatBpb->Fat32.BPB_Reserved[11]);\r
+    return FatTypeUnknown;\r
+  }\r
+  if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) &&\r
+       (FatBpb->Fat12_16.BS_Reserved1 != 0)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT12_16 - BS_Reserved1 - %02x, expected: 0\n",\r
+        FatBpb->Fat12_16.BS_Reserved1);\r
+    return FatTypeUnknown;\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat32.BS_Reserved1 != 0)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BS_Reserved1 - %02x, expected: 0\n",\r
+        FatBpb->Fat32.BS_Reserved1);\r
+    return FatTypeUnknown;\r
+  }\r
+  if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) &&\r
+       (FatBpb->Fat12_16.BS_BootSig != FAT_BS_BOOTSIG)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT12_16 - BS_BootSig - %02x, expected: %02x\n",\r
+        FatBpb->Fat12_16.BS_BootSig, FAT_BS_BOOTSIG);\r
+    return FatTypeUnknown;\r
+  }\r
+  if ((FatType == FatTypeFat32) &&\r
+      (FatBpb->Fat32.BS_BootSig != FAT_BS_BOOTSIG)) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BS_BootSig - %02x, expected: %02x\n",\r
+        FatBpb->Fat32.BS_BootSig, FAT_BS_BOOTSIG);\r
+    return FatTypeUnknown;\r
+  }\r
+  \r
+  if ((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) {\r
+    memcpy (FilSysType, FatBpb->Fat12_16.BS_FilSysType, 8);\r
+    FilSysType[8] = 0;\r
+    if ((FatType == FatTypeFat12) && \r
+        (strcmp (FilSysType, FAT12_FILSYSTYPE) != 0) &&\r
+        (strcmp (FilSysType, FAT_FILSYSTYPE) != 0)) {\r
+      DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT12 - BS_FilSysType - %s, expected: %s, or %s\n",\r
+          FilSysType, FAT12_FILSYSTYPE, FAT_FILSYSTYPE);\r
+    }\r
+    if ((FatType == FatTypeFat16) && \r
+        (strcmp (FilSysType, FAT16_FILSYSTYPE) != 0) &&\r
+        (strcmp (FilSysType, FAT_FILSYSTYPE) != 0)) {\r
+      DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT16 - BS_FilSysType - %s, expected: %s, or %s\n",\r
+          FilSysType, FAT16_FILSYSTYPE, FAT_FILSYSTYPE);\r
+    }\r
+  }\r
+  if (FatType == FatTypeFat32) {\r
+    memcpy (FilSysType, FatBpb->Fat32.BS_FilSysType, 8);\r
+    FilSysType[8] = 0;\r
+    if (strcmp (FilSysType, FAT32_FILSYSTYPE) != 0) {\r
+      DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BS_FilSysType - %s, expected: %s\n",\r
+          FilSysType, FAT32_FILSYSTYPE);\r
+    }\r
+  }\r
+\r
+  //\r
+  // pass all check, get FAT type\r
+  //\r
+  return FatType;\r
+}\r
+\r
+\r
+void\r
+ParseBootSector (\r
+  char *FileName\r
+  )\r
+{\r
+  FAT_BPB_STRUCT  FatBpb;\r
+  FAT_TYPE        FatType;\r
+  \r
+  if (ReadFromFile ((void *)&FatBpb, FileName) == 0) {\r
+    return ;\r
+  }\r
+  \r
+  FatType = GetFatType (&FatBpb);\r
+  if (FatType <= FatTypeUnknown || FatType >= FatTypeMax) {\r
+    printf ("ERROR: E3002: Unknown FAT Type!\n");\r
+    return;\r
+  }\r
+\r
+  printf ("\nBoot Sector %s:\n", FatTypeToString (FatType));\r
+  printf ("\n");\r
+  printf ("  Offset Title                        Data\n");\r
+  printf ("==================================================================\n");\r
+  printf ("  0      JMP instruction              %02x %02x %02x\n",\r
+                                                 FatBpb.Fat12_16.BS_jmpBoot[0],\r
+                                                 FatBpb.Fat12_16.BS_jmpBoot[1],\r
+                                                 FatBpb.Fat12_16.BS_jmpBoot[2]);\r
+  printf ("  3      OEM                          %c%c%c%c%c%c%c%c\n",\r
+                                                 FatBpb.Fat12_16.BS_OEMName[0],\r
+                                                 FatBpb.Fat12_16.BS_OEMName[1],\r
+                                                 FatBpb.Fat12_16.BS_OEMName[2],\r
+                                                 FatBpb.Fat12_16.BS_OEMName[3],\r
+                                                 FatBpb.Fat12_16.BS_OEMName[4],\r
+                                                 FatBpb.Fat12_16.BS_OEMName[5],\r
+                                                 FatBpb.Fat12_16.BS_OEMName[6],\r
+                                                 FatBpb.Fat12_16.BS_OEMName[7]);\r
+  printf ("\n");\r
+  printf ("BIOS Parameter Block\n");\r
+  printf ("  B      Bytes per sector             %04x\n", FatBpb.Fat12_16.BPB_BytsPerSec);\r
+  printf ("  D      Sectors per cluster          %02x\n", FatBpb.Fat12_16.BPB_SecPerClus);\r
+  printf ("  E      Reserved sectors             %04x\n", FatBpb.Fat12_16.BPB_RsvdSecCnt);\r
+  printf ("  10     Number of FATs               %02x\n", FatBpb.Fat12_16.BPB_NumFATs);\r
+  printf ("  11     Root entries                 %04x\n", FatBpb.Fat12_16.BPB_RootEntCnt);\r
+  printf ("  13     Sectors (under 32MB)         %04x\n", FatBpb.Fat12_16.BPB_TotSec16);\r
+  printf ("  15     Media descriptor             %02x\n", FatBpb.Fat12_16.BPB_Media);\r
+  printf ("  16     Sectors per FAT (small vol.) %04x\n", FatBpb.Fat12_16.BPB_FATSz16);\r
+  printf ("  18     Sectors per track            %04x\n", FatBpb.Fat12_16.BPB_SecPerTrk);\r
+  printf ("  1A     Heads                        %04x\n", FatBpb.Fat12_16.BPB_NumHeads);\r
+  printf ("  1C     Hidden sectors               %08x\n", FatBpb.Fat12_16.BPB_HiddSec);\r
+  printf ("  20     Sectors (over 32MB)          %08x\n", FatBpb.Fat12_16.BPB_TotSec32);\r
+  printf ("\n");\r
+  if (FatType != FatTypeFat32) {\r
+    printf ("  24     BIOS drive                   %02x\n", FatBpb.Fat12_16.BS_DrvNum);\r
+    printf ("  25     (Unused)                     %02x\n", FatBpb.Fat12_16.BS_Reserved1);\r
+    printf ("  26     Ext. boot signature          %02x\n", FatBpb.Fat12_16.BS_BootSig);\r
+    printf ("  27     Volume serial number         %08x\n", FatBpb.Fat12_16.BS_VolID);\r
+    printf ("  2B     Volume lable                 %c%c%c%c%c%c%c%c%c%c%c\n",\r
+                                                   FatBpb.Fat12_16.BS_VolLab[0],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[1],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[2],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[3],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[4],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[5],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[6],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[7],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[8],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[9],\r
+                                                   FatBpb.Fat12_16.BS_VolLab[10]);\r
+    printf ("  36     File system                  %c%c%c%c%c%c%c%c\n",\r
+                                                   FatBpb.Fat12_16.BS_FilSysType[0],\r
+                                                   FatBpb.Fat12_16.BS_FilSysType[1],\r
+                                                   FatBpb.Fat12_16.BS_FilSysType[2],\r
+                                                   FatBpb.Fat12_16.BS_FilSysType[3],\r
+                                                   FatBpb.Fat12_16.BS_FilSysType[4],\r
+                                                   FatBpb.Fat12_16.BS_FilSysType[5],\r
+                                                   FatBpb.Fat12_16.BS_FilSysType[6],\r
+                                                   FatBpb.Fat12_16.BS_FilSysType[7]);\r
+    printf ("\n");\r
+  } else {\r
+    printf ("FAT32 Section\n");\r
+    printf ("  24     Sectors per FAT (large vol.) %08x\n", FatBpb.Fat32.BPB_FATSz32);\r
+    printf ("  28     Flags                        %04x\n", FatBpb.Fat32.BPB_ExtFlags);\r
+    printf ("  2A     Version                      %04x\n", FatBpb.Fat32.BPB_FSVer);\r
+    printf ("  2C     Root dir 1st cluster         %08x\n", FatBpb.Fat32.BPB_RootClus);\r
+    printf ("  30     FSInfo sector                %04x\n", FatBpb.Fat32.BPB_FSInfo);\r
+    printf ("  32     Backup boot sector           %04x\n", FatBpb.Fat32.BPB_BkBootSec);\r
+    printf ("  34     (Reserved)                   %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",\r
+                                                   FatBpb.Fat32.BPB_Reserved[0],\r
+                                                   FatBpb.Fat32.BPB_Reserved[1],\r
+                                                   FatBpb.Fat32.BPB_Reserved[2],\r
+                                                   FatBpb.Fat32.BPB_Reserved[3],\r
+                                                   FatBpb.Fat32.BPB_Reserved[4],\r
+                                                   FatBpb.Fat32.BPB_Reserved[5],\r
+                                                   FatBpb.Fat32.BPB_Reserved[6],\r
+                                                   FatBpb.Fat32.BPB_Reserved[7],\r
+                                                   FatBpb.Fat32.BPB_Reserved[8],\r
+                                                   FatBpb.Fat32.BPB_Reserved[9],\r
+                                                   FatBpb.Fat32.BPB_Reserved[10],\r
+                                                   FatBpb.Fat32.BPB_Reserved[11]);\r
+    printf ("\n");\r
+    printf ("  40     BIOS drive                   %02x\n", FatBpb.Fat32.BS_DrvNum);\r
+    printf ("  41     (Unused)                     %02x\n", FatBpb.Fat32.BS_Reserved1);\r
+    printf ("  42     Ext. boot signature          %02x\n", FatBpb.Fat32.BS_BootSig);\r
+    printf ("  43     Volume serial number         %08x\n", FatBpb.Fat32.BS_VolID);\r
+    printf ("  47     Volume lable                 %c%c%c%c%c%c%c%c%c%c%c\n",\r
+                                                   FatBpb.Fat32.BS_VolLab[0],\r
+                                                   FatBpb.Fat32.BS_VolLab[1],\r
+                                                   FatBpb.Fat32.BS_VolLab[2],\r
+                                                   FatBpb.Fat32.BS_VolLab[3],\r
+                                                   FatBpb.Fat32.BS_VolLab[4],\r
+                                                   FatBpb.Fat32.BS_VolLab[5],\r
+                                                   FatBpb.Fat32.BS_VolLab[6],\r
+                                                   FatBpb.Fat32.BS_VolLab[7],\r
+                                                   FatBpb.Fat32.BS_VolLab[8],\r
+                                                   FatBpb.Fat32.BS_VolLab[9],\r
+                                                   FatBpb.Fat32.BS_VolLab[10]);\r
+    printf ("  52     File system                  %c%c%c%c%c%c%c%c\n",\r
+                                                   FatBpb.Fat32.BS_FilSysType[0],\r
+                                                   FatBpb.Fat32.BS_FilSysType[1],\r
+                                                   FatBpb.Fat32.BS_FilSysType[2],\r
+                                                   FatBpb.Fat32.BS_FilSysType[3],\r
+                                                   FatBpb.Fat32.BS_FilSysType[4],\r
+                                                   FatBpb.Fat32.BS_FilSysType[5],\r
+                                                   FatBpb.Fat32.BS_FilSysType[6],\r
+                                                   FatBpb.Fat32.BS_FilSysType[7]);\r
+    printf ("\n");\r
+  }\r
+  printf ("  1FE    Signature                    %04x\n", FatBpb.Fat12_16.Signature);\r
+  printf ("\n");\r
+\r
+  \r
+  return ;\r
+}\r
+\r
+void\r
+PatchBootSector (\r
+  char *DestFileName,\r
+  char *SourceFileName,\r
+  BOOLEAN ForcePatch\r
+  )\r
+/*++\r
+Routine Description:\r
+  Patch destination file according to the information from source file.\r
+  Only patch BPB data but leave boot code un-touched.\r
+\r
+Arguments:\r
+  DestFileName   - Destination file to patch\r
+  SourceFileName - Source file where patch from\r
+--*/\r
+{\r
+  FAT_BPB_STRUCT  DestFatBpb;\r
+  FAT_BPB_STRUCT  SourceFatBpb;\r
+  FAT_TYPE        DestFatType;\r
+  FAT_TYPE        SourceFatType;\r
+  CHAR8           VolLab[11];\r
+  CHAR8           FilSysType[8];\r
+  \r
+  if (ReadFromFile ((void *)&DestFatBpb, DestFileName) == 0) {\r
+    return ;\r
+  }\r
+  if (ReadFromFile ((void *)&SourceFatBpb, SourceFileName) == 0) {\r
+    return ;\r
+  }\r
+  \r
+  DestFatType = GetFatType (&DestFatBpb);\r
+  SourceFatType = GetFatType (&SourceFatBpb);\r
+\r
+  if (DestFatType != SourceFatType) {\r
+    //\r
+    // FAT type mismatch\r
+    //\r
+    if (ForcePatch) {\r
+      DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3004: FAT type mismatch: Source - %s, Dest - %s", \r
+        FatTypeToString(SourceFatType), FatTypeToString(DestFatType));\r
+    } else {\r
+      DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3004: FAT type mismatch: Source - %s, Dest - %s", \r
+        FatTypeToString(SourceFatType), FatTypeToString(DestFatType));\r
+      return ;\r
+    }\r
+  }\r
+\r
+  if (SourceFatType <= FatTypeUnknown || SourceFatType >= FatTypeMax) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3002: Unknown FAT Type!\n");\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Copy BPB/boot data (excluding BS_jmpBoot, BS_OEMName, BootCode and Signature) from SourceFatBpb to DestFatBpb\r
+  //\r
+  printf ("Patching %s BPB: ", FatTypeToString (SourceFatType));\r
+  if (SourceFatType != FatTypeFat32) {\r
+    memcpy (\r
+      &DestFatBpb.Fat12_16.BPB_BytsPerSec,\r
+      &SourceFatBpb.Fat12_16.BPB_BytsPerSec,\r
+      ((UINTN)&DestFatBpb.Fat12_16.Reserved - (UINTN)&DestFatBpb.Fat12_16.BPB_BytsPerSec)\r
+      );\r
+  } else {\r
+    memcpy (\r
+      &DestFatBpb.Fat32.BPB_BytsPerSec,\r
+      &SourceFatBpb.Fat32.BPB_BytsPerSec,\r
+      ((UINTN)&DestFatBpb.Fat32.Reserved - (UINTN)&DestFatBpb.Fat32.BPB_BytsPerSec)\r
+      );\r
+  }\r
+\r
+  //\r
+  // Set BS_VolLab and BS_FilSysType of DestFatBpb\r
+  //\r
+  //        BS_VolLab     BS_FilSysType\r
+  // FAT12: EFI FAT12     FAT12\r
+  // FAT16: EFI FAT16     FAT16\r
+  // FAT32: EFI FAT32     FAT32\r
+  //\r
+  if (SourceFatType == FatTypeFat32) {\r
+    memcpy (VolLab, "EFI FAT32  ", sizeof(VolLab));\r
+    memcpy (FilSysType, FAT32_FILSYSTYPE, sizeof(FilSysType));\r
+  } else if (SourceFatType == FatTypeFat16) {\r
+    memcpy (VolLab, "EFI FAT16  ", sizeof(VolLab));\r
+    memcpy (FilSysType, FAT16_FILSYSTYPE, sizeof(FilSysType));\r
+  } else {\r
+    memcpy (VolLab, "EFI FAT12  ", sizeof(VolLab));\r
+    memcpy (FilSysType, FAT12_FILSYSTYPE, sizeof(FilSysType));\r
+  }\r
+  if (SourceFatType != FatTypeFat32) {\r
+    memcpy (DestFatBpb.Fat12_16.BS_VolLab, VolLab, sizeof(VolLab));\r
+    memcpy (DestFatBpb.Fat12_16.BS_FilSysType, FilSysType, sizeof(FilSysType));\r
+  } else {\r
+    memcpy (DestFatBpb.Fat32.BS_VolLab, VolLab, sizeof(VolLab));\r
+    memcpy (DestFatBpb.Fat32.BS_FilSysType, FilSysType, sizeof(FilSysType));\r
+  }\r
+  \r
+  //\r
+  // Set Signature of DestFatBpb to 55AA\r
+  //\r
+  DestFatBpb.Fat12_16.Signature = FAT_BS_SIGNATURE;\r
+\r
+  //\r
+  // Write DestFatBpb\r
+  //\r
+  if (WriteToFile ((void *)&DestFatBpb, DestFileName)) {\r
+    printf ("successful!\n");\r
+  } else {\r
+    printf ("failed!\n");\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+void\r
+ParseMbr (\r
+  char *FileName\r
+  )\r
+{\r
+  MASTER_BOOT_RECORD  Mbr;\r
+  \r
+  if (ReadFromFile ((void *)&Mbr, FileName) == 0) {\r
+    return ;\r
+  }\r
\r
+  printf ("\nMaster Boot Record:\n");\r
+  printf ("\n");\r
+  printf ("  Offset Title                        Value\n");\r
+  printf ("==================================================================\n");\r
+  printf ("  0      Master bootstrap loader code (not list)\n");\r
+  printf ("  1B8    Windows disk signature       %08x\n", Mbr.UniqueMbrSignature);\r
+  printf ("\n");\r
+  printf ("Partition Table Entry #1\n");\r
+  printf ("  1BE    80 = active partition        %02x\n", Mbr.PartitionRecord[0].BootIndicator);\r
+  printf ("  1BF    Start head                   %02x\n", Mbr.PartitionRecord[0].StartHead);\r
+  printf ("  1C0    Start sector                 %02x\n", Mbr.PartitionRecord[0].StartSector);\r
+  printf ("  1C1    Start cylinder               %02x\n", Mbr.PartitionRecord[0].StartTrack);\r
+  printf ("  1C2    Partition type indicator     %02x\n", Mbr.PartitionRecord[0].OSType);\r
+  printf ("  1C3    End head                     %02x\n", Mbr.PartitionRecord[0].EndHead);\r
+  printf ("  1C4    End sector                   %02x\n", Mbr.PartitionRecord[0].EndSector);\r
+  printf ("  1C5    End cylinder                 %02x\n", Mbr.PartitionRecord[0].EndTrack);\r
+  printf ("  1C6    Sectors preceding partition  %08x\n", Mbr.PartitionRecord[0].StartingLBA);\r
+  printf ("  1CA    Sectors in partition         %08x\n", Mbr.PartitionRecord[0].SizeInLBA);\r
+  printf ("\n");\r
+  printf ("Partition Table Entry #2\n");\r
+  printf ("  1CE    80 = active partition        %02x\n", Mbr.PartitionRecord[1].BootIndicator);\r
+  printf ("  1CF    Start head                   %02x\n", Mbr.PartitionRecord[1].StartHead);\r
+  printf ("  1D0    Start sector                 %02x\n", Mbr.PartitionRecord[1].StartSector);\r
+  printf ("  1D1    Start cylinder               %02x\n", Mbr.PartitionRecord[1].StartTrack);\r
+  printf ("  1D2    Partition type indicator     %02x\n", Mbr.PartitionRecord[1].OSType);\r
+  printf ("  1D3    End head                     %02x\n", Mbr.PartitionRecord[1].EndHead);\r
+  printf ("  1D4    End sector                   %02x\n", Mbr.PartitionRecord[1].EndSector);\r
+  printf ("  1D5    End cylinder                 %02x\n", Mbr.PartitionRecord[1].EndTrack);\r
+  printf ("  1D6    Sectors preceding partition  %08x\n", Mbr.PartitionRecord[1].StartingLBA);\r
+  printf ("  1DA    Sectors in partition         %08x\n", Mbr.PartitionRecord[1].SizeInLBA);\r
+  printf ("\n");\r
+  printf ("Partition Table Entry #3\n");\r
+  printf ("  1DE    80 = active partition        %02x\n", Mbr.PartitionRecord[2].BootIndicator);\r
+  printf ("  1DF    Start head                   %02x\n", Mbr.PartitionRecord[2].StartHead);\r
+  printf ("  1E0    Start sector                 %02x\n", Mbr.PartitionRecord[2].StartSector);\r
+  printf ("  1E1    Start cylinder               %02x\n", Mbr.PartitionRecord[2].StartTrack);\r
+  printf ("  1E2    Partition type indicator     %02x\n", Mbr.PartitionRecord[2].OSType);\r
+  printf ("  1E3    End head                     %02x\n", Mbr.PartitionRecord[2].EndHead);\r
+  printf ("  1E4    End sector                   %02x\n", Mbr.PartitionRecord[2].EndSector);\r
+  printf ("  1E5    End cylinder                 %02x\n", Mbr.PartitionRecord[2].EndTrack);\r
+  printf ("  1E6    Sectors preceding partition  %08x\n", Mbr.PartitionRecord[2].StartingLBA);\r
+  printf ("  1EA    Sectors in partition         %08x\n", Mbr.PartitionRecord[2].SizeInLBA);\r
+  printf ("\n");\r
+  printf ("Partition Table Entry #4\n");\r
+  printf ("  1EE    80 = active partition        %02x\n", Mbr.PartitionRecord[3].BootIndicator);\r
+  printf ("  1EF    Start head                   %02x\n", Mbr.PartitionRecord[3].StartHead);\r
+  printf ("  1F0    Start sector                 %02x\n", Mbr.PartitionRecord[3].StartSector);\r
+  printf ("  1F1    Start cylinder               %02x\n", Mbr.PartitionRecord[3].StartTrack);\r
+  printf ("  1F2    Partition type indicator     %02x\n", Mbr.PartitionRecord[3].OSType);\r
+  printf ("  1F3    End head                     %02x\n", Mbr.PartitionRecord[3].EndHead);\r
+  printf ("  1F4    End sector                   %02x\n", Mbr.PartitionRecord[3].EndSector);\r
+  printf ("  1F5    End cylinder                 %02x\n", Mbr.PartitionRecord[3].EndTrack);\r
+  printf ("  1F6    Sectors preceding partition  %08x\n", Mbr.PartitionRecord[3].StartingLBA);\r
+  printf ("  1FA    Sectors in partition         %08x\n", Mbr.PartitionRecord[3].SizeInLBA);\r
+  printf ("\n");\r
+  printf ("  1FE    Signature                    %04x\n", Mbr.Signature);\r
+  printf ("\n");\r
+\r
+  return ;\r
+}\r
+\r
+void\r
+PatchMbr (\r
+  char *DestFileName,\r
+  char *SourceFileName\r
+  )\r
+{\r
+  MASTER_BOOT_RECORD  DestMbr;\r
+  MASTER_BOOT_RECORD  SourceMbr;\r
+  \r
+  if (ReadFromFile ((void *)&DestMbr, DestFileName) == 0) {\r
+    return ;\r
+  }\r
+  if (ReadFromFile ((void *)&SourceMbr, SourceFileName) == 0) {\r
+    return ;\r
+  }\r
+  \r
+  if (SourceMbr.Signature != MBR_SIGNATURE) {\r
+    printf ("ERROR: E3000: Invalid MBR!\n");\r
+    return;\r
+  }\r
+\r
+  printf ("Patching MBR:\n");\r
+  memcpy (\r
+    &DestMbr.PartitionRecord[0],\r
+    &SourceMbr.PartitionRecord[0],\r
+    sizeof(DestMbr.PartitionRecord)\r
+    );\r
+\r
+  DestMbr.Signature = MBR_SIGNATURE;\r
+\r
+\r
+  if (WriteToFile ((void *)&DestMbr, DestFileName)) {\r
+    printf ("\tsuccessful!\n");\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+\r
+int\r
+main (\r
+  int argc,\r
+  char *argv[]\r
+  )\r
+{\r
+  char *SrcImage;\r
+  char *DstImage;\r
+  BOOLEAN ForcePatch;    // -f\r
+  BOOLEAN ProcessMbr;    // -m\r
+  BOOLEAN DoParse;       // -p SrcImage or -g SrcImage DstImage\r
+  BOOLEAN Verbose;       // -v\r
+  \r
+  SrcImage = DstImage = NULL;\r
+  ForcePatch = FALSE;\r
+  ProcessMbr = FALSE;\r
+  DoParse    = TRUE;\r
+  Verbose    = FALSE;\r
+\r
+  SetUtilityName ("bootsectimage");\r
+\r
+  argc--; argv++;\r
+\r
+  if (argc == 0) {\r
+    Usage ();\r
+    return -1;\r
+  }\r
+\r
+  while (argc != 0) {\r
+    if (strcmp (*argv, "-f") == 0 || strcmp (*argv, "--force") == 0) {\r
+      ForcePatch = TRUE;\r
+    } else if (strcmp (*argv, "-p") == 0 || strcmp (*argv, "--parse") == 0) {\r
+      DoParse    = TRUE;\r
+      argc--; argv++;\r
+      if (argc < 1) {\r
+        Usage ();\r
+        return -1;\r
+      }\r
+      SrcImage   = *argv;\r
+    } else if (strcmp (*argv, "-g") == 0 || strcmp (*argv, "--patch") == 0) {\r
+      DoParse    = FALSE;\r
+      argc--; argv++;\r
+      if (argc < 2) {\r
+        Usage ();\r
+        return -1;\r
+      }\r
+      SrcImage   = *argv;\r
+      argc--; argv++;\r
+      DstImage   = *argv;\r
+    } else if (strcmp (*argv, "-m") == 0 || strcmp (*argv, "--mbr") == 0) {\r
+      ProcessMbr = TRUE;\r
+    } else if (strcmp (*argv, "-v") == 0 || strcmp (*argv, "--verbose") == 0) {\r
+      Verbose    = TRUE;\r
+    } else {\r
+      Usage ();\r
+      return -1;\r
+    }\r
+\r
+    argc--; argv++;\r
+  }\r
+\r
+  if (ForcePatch && DoParse) {\r
+    printf ("ERROR: E1002: Conflicting options: -f, -p. Cannot apply force(-f) to parse(-p)!\n");\r
+    Usage ();\r
+    return -1;\r
+  }\r
+  if (ForcePatch && !DoParse && ProcessMbr) {\r
+    printf ("ERROR: E1002: Conflicting options: -f, -g -m. Cannot apply force(-f) to processing MBR (-g -m)!\n");\r
+    Usage ();\r
+    return -1;\r
+  }\r
+\r
+  if (Verbose) {\r
+    SetPrintLevel (VERBOSE_LOG_LEVEL);\r
+  } else {\r
+    SetPrintLevel (KEY_LOG_LEVEL);\r
+  }\r
+\r
+  if (DoParse) {\r
+    if (ProcessMbr) {\r
+      ParseMbr (SrcImage);\r
+    } else {\r
+      ParseBootSector (SrcImage);\r
+    }\r
+  } else {\r
+    if (ProcessMbr) {\r
+      PatchMbr (DstImage, SrcImage);\r
+    } else {\r
+      PatchBootSector (DstImage, SrcImage, ForcePatch);\r
+    }\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r