]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/bootsectimage.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / BootsectImage / bootsectimage.c
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/bootsectimage.c b/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/bootsectimage.c
new file mode 100644 (file)
index 0000000..d71a03d
--- /dev/null
@@ -0,0 +1,881 @@
+/*++\r
+\r
+Copyright 2006 - 2007, 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
+Module Name:\r
+\r
+  bootsectimage.c\r
+    \r
+Abstract:\r
+  Patch the BPB information in boot sector image file.\r
+  Patch the MBR code in MBR image file.\r
+\r
+--*/\r
+\r
+\r
+#include <windows.h>\r
+#include <stdio.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
+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, "Open 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, "Read 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, "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, "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, "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, "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, "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, "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, "FAT: BPB_RsvdSecCnt - %04x, expected - Non-Zero",\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, "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, "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, "FAT: BPB_FATSz16, BPB_FATSz32 - 0, expected - Non-Zero");\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, "FAT: BPB_TotSec16, BPB_TotSec32 - 0, expected - Non-Zero");\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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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: 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
+  BOOL 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, "FAT type mismatch: Dest - %s, Source - %s", \r
+          FatTypeToString(DestFatType), FatTypeToString(SourceFatType));\r
+    } else {\r
+      DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT type mismatch: Dest - %s, Source - %s", \r
+          FatTypeToString(DestFatType), FatTypeToString(SourceFatType));\r
+      return ;\r
+    }\r
+  }\r
+\r
+  if (SourceFatType <= FatTypeUnknown || SourceFatType >= FatTypeMax) {\r
+    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "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 ("successfully!\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: 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 ("\tsuccessfully!\n");\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+void\r
+PrintUsage (\r
+  void\r
+  )\r
+{\r
+  printf (\r
+    "Usage:\n"\r
+    "bootsectimage [-m] [-v] -p SrcImage\n"\r
+    "bootsectimage [-m] [-v] [-f] -g SrcImage DstImage\n"\r
+    "where\n"\r
+    "  -p: parse SrcImage\n"\r
+    "  -g: get info from SrcImage, and patch to DstImage\n"\r
+    "  -f: force patch even FAT type of SrcImage and DstImage mismatch\n"\r
+    "  -m: process MBR instead of boot sector\n"\r
+    "  -v: verbose\n"\r
+    );\r
+}\r
+\r
+int\r
+main (\r
+  int argc,\r
+  char *argv[]\r
+  )\r
+{\r
+  char *SrcImage;\r
+  char *DstImage;\r
+  BOOL ForcePatch;    // -f\r
+  BOOL ProcessMbr;    // -m\r
+  BOOL DoParse;       // -p SrcImage or -g SrcImage DstImage\r
+  BOOL 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
+    PrintUsage ();\r
+    return -1;\r
+  }\r
+\r
+  while (argc != 0) {\r
+    if (strcmp (*argv, "-f") == 0) {\r
+      ForcePatch = TRUE;\r
+    } else if (strcmp (*argv, "-p") == 0) {\r
+      DoParse    = TRUE;\r
+      argc--; argv++;\r
+      if (argc < 1) {\r
+        PrintUsage ();\r
+        return -1;\r
+      }\r
+      SrcImage   = *argv;\r
+    } else if (strcmp (*argv, "-g") == 0) {\r
+      DoParse    = FALSE;\r
+      argc--; argv++;\r
+      if (argc < 2) {\r
+        PrintUsage ();\r
+        return -1;\r
+      }\r
+      SrcImage   = *argv;\r
+      argc--; argv++;\r
+      DstImage   = *argv;\r
+    } else if (strcmp (*argv, "-m") == 0) {\r
+      ProcessMbr = TRUE;\r
+    } else if (strcmp (*argv, "-v") == 0) {\r
+      Verbose    = TRUE;\r
+    } else {\r
+      PrintUsage ();\r
+      return -1;\r
+    }\r
+\r
+    argc--; argv++;\r
+  }\r
+\r
+  if (ForcePatch && DoParse) {\r
+    printf ("Cannot apply force(-f) to parse(-p)!\n");\r
+    PrintUsage ();\r
+    return -1;\r
+  }\r
+  if (ForcePatch && !DoParse && ProcessMbr) {\r
+    printf ("Cannot apply force(-f) to processing MBR (-g -m)!\n");\r
+    PrintUsage ();\r
+    return -1;\r
+  }\r
+\r
+  if (Verbose) {\r
+    SetDebugMsgMask (DEBUG_WARN | DEBUG_ERROR);\r
+  } else {\r
+    SetDebugMsgMask (0);\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