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