1/** @file
2
3Abstract:
4  Patch the BPB information in boot sector image file.
5  Patch the MBR code in MBR image file.
6
7Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
8This program and the accompanying materials
9are licensed and made available under the terms and conditions of the BSD License
10which accompanies this distribution.  The full text of the license may be found at
11http://opensource.org/licenses/bsd-license.php
12
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16**/
17
18#include <stdio.h>
19#include <string.h>
20#include "fat.h"
21#include "mbr.h"
22#include "EfiUtilityMsgs.h"
23#include "ParseInf.h"
24
25#define DEBUG_WARN  0x1
26#define DEBUG_ERROR 0x2
27
28//
29// Utility Name
30//
31#define UTILITY_NAME  "BootSectImage"
32
33//
34// Utility version information
35//
36#define UTILITY_MAJOR_VERSION 1
37#define UTILITY_MINOR_VERSION 0
38
39void
40Version (
41  void
42  )
43/*++
44
45Routine Description:
46
47  Displays the standard utility information to SDTOUT
48
49Arguments:
50
51  None
52
53Returns:
54
55  None
56
57--*/
58{
59  printf ("%s Version %d.%d Build %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
60}
61
62void
63Usage (
64  void
65  )
66/*++
67
68Routine Description:
69
70  GC_TODO: Add function description
71
72Arguments:
73
74
75Returns:
76
77  GC_TODO: add return values
78
79--*/
80{
81  Version();
82  printf ("Copyright (c) 1999-2016 Intel Corporation. All rights reserved.\n");
83  printf ("\n  The BootSectImage tool prints information or patch destination file by source\n");
84  printf ("  file for BIOS Parameter Block (BPB) or Master Boot Record (MBR).\n");
85  printf ("\nUsage: \n\
86   BootSectImage\n\
87     [-f, --force force patch even if the FAT type of SrcImage and DstImage mismatch]\n\
88     [-m, --mbr process MBR instead of boot sector]\n\
89     [-p, --parse parse SrcImageFile]\n\
90     [-o, --output DstImage]\n\
91     [-g, --patch patch DstImage using data from SrcImageFile]\n\
92     [-v, --verbose]\n\
93     [--version]\n\
94     [-q, --quiet disable all messages except fatal errors]\n\
95     [-d, --debug[#]\n\
96     [-h, --help]\n\
97     [SrcImageFile]\n");
98}
99
100int WriteToFile (
101  void *BootSector,
102  char *FileName
103  )
104/*++
105Routine Description:
106  Write 512 bytes boot sector to file.
107
108Arguments:
109  BootSector - point to a buffer containing 512 bytes boot sector to write
110  FileName   - file to write to
111
112Return:
113  int        - number of bytes wrote,
114                 512 indicates write successful
115                 0 indicates write failure
116--*/
117{
118  FILE *FileHandle;
119  int  result;
120
121  FileHandle = fopen (LongFilePath (FileName), "r+b");
122  if (FileHandle == NULL) {
123    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Open file: %s", FileName);
124    return 0;
125  }
126  fseek (FileHandle, 0, SEEK_SET);
127
128  result = fwrite (BootSector, 1, 512, FileHandle);
129  if (result != 512) {
130    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Write file: %s", FileName);
131    result = 0;
132  }
133
134  fclose (FileHandle);
135  return result;
136}
137
138int ReadFromFile (
139  void *BootSector,
140  char *FileName
141  )
142/*++
143Routine Description:
144  Read first 512 bytes from file.
145
146Arguments:
147  BootSector - point to a buffer receiving the first 512 bytes data from file
148  FileName   - file to read from
149
150Return:
151  int        - number of bytes read,
152                 512 indicates read successful
153                 0 indicates read failure
154--*/
155{
156  FILE *FileHandle;
157  int  result;
158
159  FileHandle = fopen (LongFilePath (FileName), "rb");
160  if (FileHandle == NULL) {
161    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E0001: Error opening file: %s", FileName);
162    return 0;
163  }
164
165  result = fread (BootSector, 1, 512, FileHandle);
166  if (result != 512) {
167    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E0004: Error reading file: %s", FileName);
168    result = 0;
169  }
170
171  fclose (FileHandle);
172  return result;
173}
174
175char *
176FatTypeToString (
177  IN FAT_TYPE        FatType
178  )
179/*++
180Routine Description:
181  Convert enum type of FatType to string
182--*/
183{
184  switch (FatType) {
185  case FatTypeFat12:
186    return "FAT12";
187  case FatTypeFat16:
188    return "FAT16";
189  case FatTypeFat32:
190    return "FAT32";
191  default:
192    break;
193  }
194  return "FAT Unknown";
195}
196
197FAT_TYPE
198GetFatType (
199  IN FAT_BPB_STRUCT  *FatBpb
200  )
201/*++
202Routine Description:
203  Determine the FAT type according to BIOS Paramater Block (BPB) data
204
205Arguments:
206  FatBpb - BIOS Parameter Block (BPB) data, 512 Bytes
207
208Return:
209  FatTypeUnknown - Cannot determine the FAT type
210  FatTypeFat12   - FAT12
211  FatTypeFat16   - FAT16
212  FatTypeFat32   - FAT32
213--*/
214{
215  FAT_TYPE FatType;
216  UINTN    RootDirSectors;
217  UINTN    FATSz;
218  UINTN    TotSec;
219  UINTN    DataSec;
220  UINTN    CountOfClusters;
221  CHAR8    FilSysType[9];
222
223  FatType = FatTypeUnknown;
224
225  //
226  // Simple check
227  //
228  if (FatBpb->Fat12_16.Signature != FAT_BS_SIGNATURE) {
229    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - Signature Invalid - %04x, expected: %04x",
230        FatBpb->Fat12_16.Signature, FAT_BS_SIGNATURE);
231    return FatTypeUnknown;
232  }
233
234  //
235  // Check according to FAT spec
236  //
237  if ((FatBpb->Fat12_16.BS_jmpBoot[0] != FAT_BS_JMP1) &&
238      (FatBpb->Fat12_16.BS_jmpBoot[0] != FAT_BS_JMP2)) {
239    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BS_jmpBoot - %02x, expected: %02x or %02x",
240        FatBpb->Fat12_16.BS_jmpBoot[0], FAT_BS_JMP1, FAT_BS_JMP2);
241    return FatTypeUnknown;
242  }
243
244  if ((FatBpb->Fat12_16.BPB_BytsPerSec != 512) &&
245      (FatBpb->Fat12_16.BPB_BytsPerSec != 1024) &&
246      (FatBpb->Fat12_16.BPB_BytsPerSec != 2048) &&
247      (FatBpb->Fat12_16.BPB_BytsPerSec != 4096)) {
248    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_BytsPerSec - %04x, expected: %04x, %04x, %04x, or %04x",
249        FatBpb->Fat12_16.BPB_BytsPerSec, 512, 1024, 2048, 4096);
250    return FatTypeUnknown;
251  }
252  if (FatBpb->Fat12_16.BPB_BytsPerSec != 512) {
253    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT - BPB_BytsPerSec - %04x, expected: %04x",
254        FatBpb->Fat12_16.BPB_BytsPerSec, 512);
255  }
256  if ((FatBpb->Fat12_16.BPB_SecPerClus != 1) &&
257      (FatBpb->Fat12_16.BPB_SecPerClus != 2) &&
258      (FatBpb->Fat12_16.BPB_SecPerClus != 4) &&
259      (FatBpb->Fat12_16.BPB_SecPerClus != 8) &&
260      (FatBpb->Fat12_16.BPB_SecPerClus != 16) &&
261      (FatBpb->Fat12_16.BPB_SecPerClus != 32) &&
262      (FatBpb->Fat12_16.BPB_SecPerClus != 64) &&
263      (FatBpb->Fat12_16.BPB_SecPerClus != 128)) {
264    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_SecPerClus - %02x, expected: %02x, %02x, %02x, %02x, %02x, %02x, %02x, or %02x",
265        FatBpb->Fat12_16.BPB_BytsPerSec, 1, 2, 4, 8, 16, 32, 64, 128);
266    return FatTypeUnknown;
267  }
268  if (FatBpb->Fat12_16.BPB_BytsPerSec * FatBpb->Fat12_16.BPB_SecPerClus > 32 * 1024) {
269    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_BytsPerSec * BPB_SecPerClus - %08x, expected: <= %08x",
270        FatBpb->Fat12_16.BPB_BytsPerSec * FatBpb->Fat12_16.BPB_SecPerClus, 32 * 1024);
271    return FatTypeUnknown;
272  }
273  if (FatBpb->Fat12_16.BPB_RsvdSecCnt == 0) {
274    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_RsvdSecCnt - %04x, expected: Non-Zero Value",
275        FatBpb->Fat12_16.BPB_RsvdSecCnt);
276    return FatTypeUnknown;
277  }
278  if (FatBpb->Fat12_16.BPB_NumFATs != 2) {
279    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT - BPB_NumFATs - %02x, expected: %02x",
280        FatBpb->Fat12_16.BPB_NumFATs, 2);
281  }
282  if ((FatBpb->Fat12_16.BPB_Media != 0xF0) &&
283      (FatBpb->Fat12_16.BPB_Media != 0xF8) &&
284      (FatBpb->Fat12_16.BPB_Media != 0xF9) &&
285      (FatBpb->Fat12_16.BPB_Media != 0xFA) &&
286      (FatBpb->Fat12_16.BPB_Media != 0xFB) &&
287      (FatBpb->Fat12_16.BPB_Media != 0xFC) &&
288      (FatBpb->Fat12_16.BPB_Media != 0xFD) &&
289      (FatBpb->Fat12_16.BPB_Media != 0xFE) &&
290      (FatBpb->Fat12_16.BPB_Media != 0xFF)) {
291    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_Media - %02x, expected: %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, or %02x",
292        FatBpb->Fat12_16.BPB_Media, 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF);
293    return FatTypeUnknown;
294  }
295
296  //
297  // Algo in FAT spec
298  //
299  RootDirSectors = ((FatBpb->Fat12_16.BPB_RootEntCnt * sizeof(FAT_DIRECTORY_ENTRY)) +
300                    (FatBpb->Fat12_16.BPB_BytsPerSec - 1)) /
301                   FatBpb->Fat12_16.BPB_BytsPerSec;
302
303  if (FatBpb->Fat12_16.BPB_FATSz16 != 0) {
304    FATSz = FatBpb->Fat12_16.BPB_FATSz16;
305  } else {
306    FATSz = FatBpb->Fat32.BPB_FATSz32;
307  }
308  if (FATSz == 0) {
309    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_FATSz16, BPB_FATSz32 - 0, expected: Non-Zero Value");
310    return FatTypeUnknown;
311  }
312
313  if (FatBpb->Fat12_16.BPB_TotSec16 != 0) {
314    TotSec = FatBpb->Fat12_16.BPB_TotSec16;
315  } else {
316    TotSec = FatBpb->Fat12_16.BPB_TotSec32;
317  }
318  if (TotSec == 0) {
319    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT - BPB_TotSec16, BPB_TotSec32 - 0, expected: Non-Zero Value");
320    return FatTypeUnknown;
321  }
322
323  DataSec = TotSec - (
324                      FatBpb->Fat12_16.BPB_RsvdSecCnt +
325                      FatBpb->Fat12_16.BPB_NumFATs * FATSz +
326                      RootDirSectors
327                     );
328
329  CountOfClusters = DataSec / FatBpb->Fat12_16.BPB_SecPerClus;
330
331  if (CountOfClusters < FAT_MAX_FAT12_CLUSTER) {
332    FatType = FatTypeFat12;
333  } else if (CountOfClusters < FAT_MAX_FAT16_CLUSTER) {
334    FatType = FatTypeFat16;
335  } else {
336    FatType = FatTypeFat32;
337  }
338  //
339  // Check according to FAT spec
340  //
341  if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) &&
342       (FatBpb->Fat12_16.BPB_RsvdSecCnt != 1)) {
343    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT12_16 - BPB_RsvdSecCnt - %04x, expected: %04x",
344        FatBpb->Fat12_16.BPB_RsvdSecCnt, 1);
345  }
346  if ((FatType == FatTypeFat32) &&
347       (FatBpb->Fat12_16.BPB_RsvdSecCnt != 32)) {
348    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_RsvdSecCnt - %04x, expected: %04x",
349        FatBpb->Fat12_16.BPB_RsvdSecCnt, 32);
350  }
351  if ((FatType == FatTypeFat16) &&
352      (FatBpb->Fat12_16.BPB_RootEntCnt != 512)) {
353    printf ("WARNING: FAT16: BPB_RootEntCnt - %04x, expected - %04x\n",
354        FatBpb->Fat12_16.BPB_RootEntCnt, 512);
355  }
356  if ((FatType == FatTypeFat32) &&
357      (FatBpb->Fat12_16.BPB_RootEntCnt != 0)) {
358    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_RootEntCnt - %04x, expected: %04x",
359        FatBpb->Fat12_16.BPB_RootEntCnt, 0);
360    return FatTypeUnknown;
361  }
362  if ((FatType == FatTypeFat32) &&
363      (FatBpb->Fat12_16.BPB_TotSec16 != 0)) {
364    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_TotSec16 - %04x, expected: %04x",
365        FatBpb->Fat12_16.BPB_TotSec16, 0);
366    return FatTypeUnknown;
367  }
368  if ((FatType == FatTypeFat32) &&
369      (FatBpb->Fat12_16.BPB_FATSz16 != 0)) {
370    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_FATSz16 - %04x, expected: %04x",
371        FatBpb->Fat12_16.BPB_FATSz16, 0);
372    return FatTypeUnknown;
373  }
374  if ((FatType == FatTypeFat32) &&
375      (FatBpb->Fat12_16.BPB_TotSec32 == 0)) {
376    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_TotSec32 - %04x, expected: Non-Zero",
377        (unsigned) FatBpb->Fat12_16.BPB_TotSec32);
378    return FatTypeUnknown;
379  }
380  if ((FatType == FatTypeFat32) &&
381      (FatBpb->Fat32.BPB_FATSz32 == 0)) {
382    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BPB_FATSz32 - %08x, expected: Non-Zero",
383        (unsigned) FatBpb->Fat32.BPB_FATSz32);
384    return FatTypeUnknown;
385  }
386  if ((FatType == FatTypeFat32) &&
387      (FatBpb->Fat32.BPB_FSVer != 0)) {
388    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_FSVer - %08x, expected: %04x",
389        FatBpb->Fat32.BPB_FSVer, 0);
390  }
391  if ((FatType == FatTypeFat32) &&
392      (FatBpb->Fat32.BPB_RootClus != 2)) {
393    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_RootClus - %08x, expected: %04x",
394        (unsigned) FatBpb->Fat32.BPB_RootClus, 2);
395  }
396  if ((FatType == FatTypeFat32) &&
397      (FatBpb->Fat32.BPB_FSInfo != 1)) {
398    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_FSInfo - %08x, expected: %04x",
399        FatBpb->Fat32.BPB_FSInfo, 1);
400  }
401  if ((FatType == FatTypeFat32) &&
402      (FatBpb->Fat32.BPB_BkBootSec != 6)) {
403    DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BPB_BkBootSec - %08x, expected: %04x",
404        FatBpb->Fat32.BPB_BkBootSec, 6);
405  }
406  if ((FatType == FatTypeFat32) &&
407      ((*(UINT32 *)FatBpb->Fat32.BPB_Reserved != 0) ||
408       (*((UINT32 *)FatBpb->Fat32.BPB_Reserved + 1) != 0) ||
409       (*((UINT32 *)FatBpb->Fat32.BPB_Reserved + 2) != 0))) {
410    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",
411        FatBpb->Fat32.BPB_Reserved[0],
412        FatBpb->Fat32.BPB_Reserved[1],
413        FatBpb->Fat32.BPB_Reserved[2],
414        FatBpb->Fat32.BPB_Reserved[3],
415        FatBpb->Fat32.BPB_Reserved[4],
416        FatBpb->Fat32.BPB_Reserved[5],
417        FatBpb->Fat32.BPB_Reserved[6],
418        FatBpb->Fat32.BPB_Reserved[7],
419        FatBpb->Fat32.BPB_Reserved[8],
420        FatBpb->Fat32.BPB_Reserved[9],
421        FatBpb->Fat32.BPB_Reserved[10],
422        FatBpb->Fat32.BPB_Reserved[11]);
423    return FatTypeUnknown;
424  }
425  if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) &&
426       (FatBpb->Fat12_16.BS_Reserved1 != 0)) {
427    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT12_16 - BS_Reserved1 - %02x, expected: 0\n",
428        FatBpb->Fat12_16.BS_Reserved1);
429    return FatTypeUnknown;
430  }
431  if ((FatType == FatTypeFat32) &&
432      (FatBpb->Fat32.BS_Reserved1 != 0)) {
433    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BS_Reserved1 - %02x, expected: 0\n",
434        FatBpb->Fat32.BS_Reserved1);
435    return FatTypeUnknown;
436  }
437  if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) &&
438       (FatBpb->Fat12_16.BS_BootSig != FAT_BS_BOOTSIG)) {
439    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT12_16 - BS_BootSig - %02x, expected: %02x\n",
440        FatBpb->Fat12_16.BS_BootSig, FAT_BS_BOOTSIG);
441    return FatTypeUnknown;
442  }
443  if ((FatType == FatTypeFat32) &&
444      (FatBpb->Fat32.BS_BootSig != FAT_BS_BOOTSIG)) {
445    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3003: FAT32 - BS_BootSig - %02x, expected: %02x\n",
446        FatBpb->Fat32.BS_BootSig, FAT_BS_BOOTSIG);
447    return FatTypeUnknown;
448  }
449
450  if ((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) {
451    memcpy (FilSysType, FatBpb->Fat12_16.BS_FilSysType, 8);
452    FilSysType[8] = 0;
453    if ((FatType == FatTypeFat12) &&
454        (strcmp (FilSysType, FAT12_FILSYSTYPE) != 0) &&
455        (strcmp (FilSysType, FAT_FILSYSTYPE) != 0)) {
456      DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT12 - BS_FilSysType - %s, expected: %s, or %s\n",
457          FilSysType, FAT12_FILSYSTYPE, FAT_FILSYSTYPE);
458    }
459    if ((FatType == FatTypeFat16) &&
460        (strcmp (FilSysType, FAT16_FILSYSTYPE) != 0) &&
461        (strcmp (FilSysType, FAT_FILSYSTYPE) != 0)) {
462      DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT16 - BS_FilSysType - %s, expected: %s, or %s\n",
463          FilSysType, FAT16_FILSYSTYPE, FAT_FILSYSTYPE);
464    }
465  }
466  if (FatType == FatTypeFat32) {
467    memcpy (FilSysType, FatBpb->Fat32.BS_FilSysType, 8);
468    FilSysType[8] = 0;
469    if (strcmp (FilSysType, FAT32_FILSYSTYPE) != 0) {
470      DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3003: FAT32 - BS_FilSysType - %s, expected: %s\n",
471          FilSysType, FAT32_FILSYSTYPE);
472    }
473  }
474
475  //
476  // pass all check, get FAT type
477  //
478  return FatType;
479}
480
481
482void
483ParseBootSector (
484  char *FileName
485  )
486{
487  FAT_BPB_STRUCT  FatBpb;
488  FAT_TYPE        FatType;
489
490  if (ReadFromFile ((void *)&FatBpb, FileName) == 0) {
491    return ;
492  }
493
494  FatType = GetFatType (&FatBpb);
495  if (FatType <= FatTypeUnknown || FatType >= FatTypeMax) {
496    printf ("ERROR: E3002: Unknown FAT Type!\n");
497    return;
498  }
499
500  printf ("\nBoot Sector %s:\n", FatTypeToString (FatType));
501  printf ("\n");
502  printf ("  Offset Title                        Data\n");
503  printf ("==================================================================\n");
504  printf ("  0      JMP instruction              %02x %02x %02x\n",
505                                                 FatBpb.Fat12_16.BS_jmpBoot[0],
506                                                 FatBpb.Fat12_16.BS_jmpBoot[1],
507                                                 FatBpb.Fat12_16.BS_jmpBoot[2]);
508  printf ("  3      OEM                          %c%c%c%c%c%c%c%c\n",
509                                                 FatBpb.Fat12_16.BS_OEMName[0],
510                                                 FatBpb.Fat12_16.BS_OEMName[1],
511                                                 FatBpb.Fat12_16.BS_OEMName[2],
512                                                 FatBpb.Fat12_16.BS_OEMName[3],
513                                                 FatBpb.Fat12_16.BS_OEMName[4],
514                                                 FatBpb.Fat12_16.BS_OEMName[5],
515                                                 FatBpb.Fat12_16.BS_OEMName[6],
516                                                 FatBpb.Fat12_16.BS_OEMName[7]);
517  printf ("\n");
518  printf ("BIOS Parameter Block\n");
519  printf ("  B      Bytes per sector             %04x\n", FatBpb.Fat12_16.BPB_BytsPerSec);
520  printf ("  D      Sectors per cluster          %02x\n", FatBpb.Fat12_16.BPB_SecPerClus);
521  printf ("  E      Reserved sectors             %04x\n", FatBpb.Fat12_16.BPB_RsvdSecCnt);
522  printf ("  10     Number of FATs               %02x\n", FatBpb.Fat12_16.BPB_NumFATs);
523  printf ("  11     Root entries                 %04x\n", FatBpb.Fat12_16.BPB_RootEntCnt);
524  printf ("  13     Sectors (under 32MB)         %04x\n", FatBpb.Fat12_16.BPB_TotSec16);
525  printf ("  15     Media descriptor             %02x\n", FatBpb.Fat12_16.BPB_Media);
526  printf ("  16     Sectors per FAT (small vol.) %04x\n", FatBpb.Fat12_16.BPB_FATSz16);
527  printf ("  18     Sectors per track            %04x\n", FatBpb.Fat12_16.BPB_SecPerTrk);
528  printf ("  1A     Heads                        %04x\n", FatBpb.Fat12_16.BPB_NumHeads);
529  printf ("  1C     Hidden sectors               %08x\n", (unsigned) FatBpb.Fat12_16.BPB_HiddSec);
530  printf ("  20     Sectors (over 32MB)          %08x\n", (unsigned) FatBpb.Fat12_16.BPB_TotSec32);
531  printf ("\n");
532  if (FatType != FatTypeFat32) {
533    printf ("  24     BIOS drive                   %02x\n", FatBpb.Fat12_16.BS_DrvNum);
534    printf ("  25     (Unused)                     %02x\n", FatBpb.Fat12_16.BS_Reserved1);
535    printf ("  26     Ext. boot signature          %02x\n", FatBpb.Fat12_16.BS_BootSig);
536    printf ("  27     Volume serial number         %08x\n", (unsigned) FatBpb.Fat12_16.BS_VolID);
537    printf ("  2B     Volume lable                 %c%c%c%c%c%c%c%c%c%c%c\n",
538                                                   FatBpb.Fat12_16.BS_VolLab[0],
539                                                   FatBpb.Fat12_16.BS_VolLab[1],
540                                                   FatBpb.Fat12_16.BS_VolLab[2],
541                                                   FatBpb.Fat12_16.BS_VolLab[3],
542                                                   FatBpb.Fat12_16.BS_VolLab[4],
543                                                   FatBpb.Fat12_16.BS_VolLab[5],
544                                                   FatBpb.Fat12_16.BS_VolLab[6],
545                                                   FatBpb.Fat12_16.BS_VolLab[7],
546                                                   FatBpb.Fat12_16.BS_VolLab[8],
547                                                   FatBpb.Fat12_16.BS_VolLab[9],
548                                                   FatBpb.Fat12_16.BS_VolLab[10]);
549    printf ("  36     File system                  %c%c%c%c%c%c%c%c\n",
550                                                   FatBpb.Fat12_16.BS_FilSysType[0],
551                                                   FatBpb.Fat12_16.BS_FilSysType[1],
552                                                   FatBpb.Fat12_16.BS_FilSysType[2],
553                                                   FatBpb.Fat12_16.BS_FilSysType[3],
554                                                   FatBpb.Fat12_16.BS_FilSysType[4],
555                                                   FatBpb.Fat12_16.BS_FilSysType[5],
556                                                   FatBpb.Fat12_16.BS_FilSysType[6],
557                                                   FatBpb.Fat12_16.BS_FilSysType[7]);
558    printf ("\n");
559  } else {
560    printf ("FAT32 Section\n");
561    printf ("  24     Sectors per FAT (large vol.) %08x\n", (unsigned) FatBpb.Fat32.BPB_FATSz32);
562    printf ("  28     Flags                        %04x\n", FatBpb.Fat32.BPB_ExtFlags);
563    printf ("  2A     Version                      %04x\n", FatBpb.Fat32.BPB_FSVer);
564    printf ("  2C     Root dir 1st cluster         %08x\n", (unsigned) FatBpb.Fat32.BPB_RootClus);
565    printf ("  30     FSInfo sector                %04x\n", FatBpb.Fat32.BPB_FSInfo);
566    printf ("  32     Backup boot sector           %04x\n", FatBpb.Fat32.BPB_BkBootSec);
567    printf ("  34     (Reserved)                   %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
568                                                   FatBpb.Fat32.BPB_Reserved[0],
569                                                   FatBpb.Fat32.BPB_Reserved[1],
570                                                   FatBpb.Fat32.BPB_Reserved[2],
571                                                   FatBpb.Fat32.BPB_Reserved[3],
572                                                   FatBpb.Fat32.BPB_Reserved[4],
573                                                   FatBpb.Fat32.BPB_Reserved[5],
574                                                   FatBpb.Fat32.BPB_Reserved[6],
575                                                   FatBpb.Fat32.BPB_Reserved[7],
576                                                   FatBpb.Fat32.BPB_Reserved[8],
577                                                   FatBpb.Fat32.BPB_Reserved[9],
578                                                   FatBpb.Fat32.BPB_Reserved[10],
579                                                   FatBpb.Fat32.BPB_Reserved[11]);
580    printf ("\n");
581    printf ("  40     BIOS drive                   %02x\n", FatBpb.Fat32.BS_DrvNum);
582    printf ("  41     (Unused)                     %02x\n", FatBpb.Fat32.BS_Reserved1);
583    printf ("  42     Ext. boot signature          %02x\n", FatBpb.Fat32.BS_BootSig);
584    printf ("  43     Volume serial number         %08x\n", (unsigned) FatBpb.Fat32.BS_VolID);
585    printf ("  47     Volume lable                 %c%c%c%c%c%c%c%c%c%c%c\n",
586                                                   FatBpb.Fat32.BS_VolLab[0],
587                                                   FatBpb.Fat32.BS_VolLab[1],
588                                                   FatBpb.Fat32.BS_VolLab[2],
589                                                   FatBpb.Fat32.BS_VolLab[3],
590                                                   FatBpb.Fat32.BS_VolLab[4],
591                                                   FatBpb.Fat32.BS_VolLab[5],
592                                                   FatBpb.Fat32.BS_VolLab[6],
593                                                   FatBpb.Fat32.BS_VolLab[7],
594                                                   FatBpb.Fat32.BS_VolLab[8],
595                                                   FatBpb.Fat32.BS_VolLab[9],
596                                                   FatBpb.Fat32.BS_VolLab[10]);
597    printf ("  52     File system                  %c%c%c%c%c%c%c%c\n",
598                                                   FatBpb.Fat32.BS_FilSysType[0],
599                                                   FatBpb.Fat32.BS_FilSysType[1],
600                                                   FatBpb.Fat32.BS_FilSysType[2],
601                                                   FatBpb.Fat32.BS_FilSysType[3],
602                                                   FatBpb.Fat32.BS_FilSysType[4],
603                                                   FatBpb.Fat32.BS_FilSysType[5],
604                                                   FatBpb.Fat32.BS_FilSysType[6],
605                                                   FatBpb.Fat32.BS_FilSysType[7]);
606    printf ("\n");
607  }
608  printf ("  1FE    Signature                    %04x\n", FatBpb.Fat12_16.Signature);
609  printf ("\n");
610
611
612  return ;
613}
614
615void
616PatchBootSector (
617  char *DestFileName,
618  char *SourceFileName,
619  BOOLEAN ForcePatch
620  )
621/*++
622Routine Description:
623  Patch destination file according to the information from source file.
624  Only patch BPB data but leave boot code un-touched.
625
626Arguments:
627  DestFileName   - Destination file to patch
628  SourceFileName - Source file where patch from
629--*/
630{
631  FAT_BPB_STRUCT  DestFatBpb;
632  FAT_BPB_STRUCT  SourceFatBpb;
633  FAT_TYPE        DestFatType;
634  FAT_TYPE        SourceFatType;
635  CHAR8           VolLab[11];
636  CHAR8           FilSysType[8];
637
638  if (ReadFromFile ((void *)&DestFatBpb, DestFileName) == 0) {
639    return ;
640  }
641  if (ReadFromFile ((void *)&SourceFatBpb, SourceFileName) == 0) {
642    return ;
643  }
644
645  DestFatType = GetFatType (&DestFatBpb);
646  SourceFatType = GetFatType (&SourceFatBpb);
647
648  if (DestFatType != SourceFatType) {
649    //
650    // FAT type mismatch
651    //
652    if (ForcePatch) {
653      DebugMsg (NULL, 0, DEBUG_WARN, NULL, "ERROR: E3004: FAT type mismatch: Source - %s, Dest - %s",
654        FatTypeToString(SourceFatType), FatTypeToString(DestFatType));
655    } else {
656      DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3004: FAT type mismatch: Source - %s, Dest - %s",
657        FatTypeToString(SourceFatType), FatTypeToString(DestFatType));
658      return ;
659    }
660  }
661
662  if (SourceFatType <= FatTypeUnknown || SourceFatType >= FatTypeMax) {
663    DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "ERROR: E3002: Unknown FAT Type!\n");
664    return;
665  }
666
667  //
668  // Copy BPB/boot data (excluding BS_jmpBoot, BS_OEMName, BootCode and Signature) from SourceFatBpb to DestFatBpb
669  //
670  printf ("Patching %s BPB: ", FatTypeToString (SourceFatType));
671  if (SourceFatType != FatTypeFat32) {
672    memcpy (
673      &DestFatBpb.Fat12_16.BPB_BytsPerSec,
674      &SourceFatBpb.Fat12_16.BPB_BytsPerSec,
675      ((UINTN)&DestFatBpb.Fat12_16.Reserved - (UINTN)&DestFatBpb.Fat12_16.BPB_BytsPerSec)
676      );
677  } else {
678    memcpy (
679      &DestFatBpb.Fat32.BPB_BytsPerSec,
680      &SourceFatBpb.Fat32.BPB_BytsPerSec,
681      ((UINTN)&DestFatBpb.Fat32.Reserved - (UINTN)&DestFatBpb.Fat32.BPB_BytsPerSec)
682      );
683  }
684
685  //
686  // Set BS_VolLab and BS_FilSysType of DestFatBpb
687  //
688  //        BS_VolLab     BS_FilSysType
689  // FAT12: EFI FAT12     FAT12
690  // FAT16: EFI FAT16     FAT16
691  // FAT32: EFI FAT32     FAT32
692  //
693  if (SourceFatType == FatTypeFat32) {
694    memcpy (VolLab, "EFI FAT32  ", sizeof(VolLab));
695    memcpy (FilSysType, FAT32_FILSYSTYPE, sizeof(FilSysType));
696  } else if (SourceFatType == FatTypeFat16) {
697    memcpy (VolLab, "EFI FAT16  ", sizeof(VolLab));
698    memcpy (FilSysType, FAT16_FILSYSTYPE, sizeof(FilSysType));
699  } else {
700    memcpy (VolLab, "EFI FAT12  ", sizeof(VolLab));
701    memcpy (FilSysType, FAT12_FILSYSTYPE, sizeof(FilSysType));
702  }
703  if (SourceFatType != FatTypeFat32) {
704    memcpy (DestFatBpb.Fat12_16.BS_VolLab, VolLab, sizeof(VolLab));
705    memcpy (DestFatBpb.Fat12_16.BS_FilSysType, FilSysType, sizeof(FilSysType));
706  } else {
707    memcpy (DestFatBpb.Fat32.BS_VolLab, VolLab, sizeof(VolLab));
708    memcpy (DestFatBpb.Fat32.BS_FilSysType, FilSysType, sizeof(FilSysType));
709  }
710
711  //
712  // Set Signature of DestFatBpb to 55AA
713  //
714  DestFatBpb.Fat12_16.Signature = FAT_BS_SIGNATURE;
715
716  //
717  // Write DestFatBpb
718  //
719  if (WriteToFile ((void *)&DestFatBpb, DestFileName)) {
720    printf ("successful!\n");
721  } else {
722    printf ("failed!\n");
723  }
724
725  return ;
726}
727
728void
729ParseMbr (
730  char *FileName
731  )
732{
733  MASTER_BOOT_RECORD  Mbr;
734
735  if (ReadFromFile ((void *)&Mbr, FileName) == 0) {
736    return ;
737  }
738
739  printf ("\nMaster Boot Record:\n");
740  printf ("\n");
741  printf ("  Offset Title                        Value\n");
742  printf ("==================================================================\n");
743  printf ("  0      Master bootstrap loader code (not list)\n");
744  printf ("  1B8    Windows disk signature       %08x\n", (unsigned) Mbr.UniqueMbrSignature);
745  printf ("\n");
746  printf ("Partition Table Entry #1\n");
747  printf ("  1BE    80 = active partition        %02x\n", Mbr.PartitionRecord[0].BootIndicator);
748  printf ("  1BF    Start head                   %02x\n", Mbr.PartitionRecord[0].StartHead);
749  printf ("  1C0    Start sector                 %02x\n", Mbr.PartitionRecord[0].StartSector);
750  printf ("  1C1    Start cylinder               %02x\n", Mbr.PartitionRecord[0].StartTrack);
751  printf ("  1C2    Partition type indicator     %02x\n", Mbr.PartitionRecord[0].OSType);
752  printf ("  1C3    End head                     %02x\n", Mbr.PartitionRecord[0].EndHead);
753  printf ("  1C4    End sector                   %02x\n", Mbr.PartitionRecord[0].EndSector);
754  printf ("  1C5    End cylinder                 %02x\n", Mbr.PartitionRecord[0].EndTrack);
755  printf ("  1C6    Sectors preceding partition  %08x\n", (unsigned) Mbr.PartitionRecord[0].StartingLBA);
756  printf ("  1CA    Sectors in partition         %08x\n", (unsigned) Mbr.PartitionRecord[0].SizeInLBA);
757  printf ("\n");
758  printf ("Partition Table Entry #2\n");
759  printf ("  1CE    80 = active partition        %02x\n", Mbr.PartitionRecord[1].BootIndicator);
760  printf ("  1CF    Start head                   %02x\n", Mbr.PartitionRecord[1].StartHead);
761  printf ("  1D0    Start sector                 %02x\n", Mbr.PartitionRecord[1].StartSector);
762  printf ("  1D1    Start cylinder               %02x\n", Mbr.PartitionRecord[1].StartTrack);
763  printf ("  1D2    Partition type indicator     %02x\n", Mbr.PartitionRecord[1].OSType);
764  printf ("  1D3    End head                     %02x\n", Mbr.PartitionRecord[1].EndHead);
765  printf ("  1D4    End sector                   %02x\n", Mbr.PartitionRecord[1].EndSector);
766  printf ("  1D5    End cylinder                 %02x\n", Mbr.PartitionRecord[1].EndTrack);
767  printf ("  1D6    Sectors preceding partition  %08x\n", (unsigned) Mbr.PartitionRecord[1].StartingLBA);
768  printf ("  1DA    Sectors in partition         %08x\n", (unsigned) Mbr.PartitionRecord[1].SizeInLBA);
769  printf ("\n");
770  printf ("Partition Table Entry #3\n");
771  printf ("  1DE    80 = active partition        %02x\n", Mbr.PartitionRecord[2].BootIndicator);
772  printf ("  1DF    Start head                   %02x\n", Mbr.PartitionRecord[2].StartHead);
773  printf ("  1E0    Start sector                 %02x\n", Mbr.PartitionRecord[2].StartSector);
774  printf ("  1E1    Start cylinder               %02x\n", Mbr.PartitionRecord[2].StartTrack);
775  printf ("  1E2    Partition type indicator     %02x\n", Mbr.PartitionRecord[2].OSType);
776  printf ("  1E3    End head                     %02x\n", Mbr.PartitionRecord[2].EndHead);
777  printf ("  1E4    End sector                   %02x\n", Mbr.PartitionRecord[2].EndSector);
778  printf ("  1E5    End cylinder                 %02x\n", Mbr.PartitionRecord[2].EndTrack);
779  printf ("  1E6    Sectors preceding partition  %08x\n", (unsigned) Mbr.PartitionRecord[2].StartingLBA);
780  printf ("  1EA    Sectors in partition         %08x\n", (unsigned) Mbr.PartitionRecord[2].SizeInLBA);
781  printf ("\n");
782  printf ("Partition Table Entry #4\n");
783  printf ("  1EE    80 = active partition        %02x\n", Mbr.PartitionRecord[3].BootIndicator);
784  printf ("  1EF    Start head                   %02x\n", Mbr.PartitionRecord[3].StartHead);
785  printf ("  1F0    Start sector                 %02x\n", Mbr.PartitionRecord[3].StartSector);
786  printf ("  1F1    Start cylinder               %02x\n", Mbr.PartitionRecord[3].StartTrack);
787  printf ("  1F2    Partition type indicator     %02x\n", Mbr.PartitionRecord[3].OSType);
788  printf ("  1F3    End head                     %02x\n", Mbr.PartitionRecord[3].EndHead);
789  printf ("  1F4    End sector                   %02x\n", Mbr.PartitionRecord[3].EndSector);
790  printf ("  1F5    End cylinder                 %02x\n", Mbr.PartitionRecord[3].EndTrack);
791  printf ("  1F6    Sectors preceding partition  %08x\n", (unsigned) Mbr.PartitionRecord[3].StartingLBA);
792  printf ("  1FA    Sectors in partition         %08x\n", (unsigned) Mbr.PartitionRecord[3].SizeInLBA);
793  printf ("\n");
794  printf ("  1FE    Signature                    %04x\n", Mbr.Signature);
795  printf ("\n");
796
797  return ;
798}
799
800void
801PatchMbr (
802  char *DestFileName,
803  char *SourceFileName
804  )
805{
806  MASTER_BOOT_RECORD  DestMbr;
807  MASTER_BOOT_RECORD  SourceMbr;
808
809  if (ReadFromFile ((void *)&DestMbr, DestFileName) == 0) {
810    return ;
811  }
812  if (ReadFromFile ((void *)&SourceMbr, SourceFileName) == 0) {
813    return ;
814  }
815
816  if (SourceMbr.Signature != MBR_SIGNATURE) {
817    printf ("ERROR: E3000: Invalid MBR!\n");
818    return;
819  }
820
821  printf ("Patching MBR:\n");
822  memcpy (
823    &DestMbr.PartitionRecord[0],
824    &SourceMbr.PartitionRecord[0],
825    sizeof(DestMbr.PartitionRecord)
826    );
827
828  DestMbr.Signature = MBR_SIGNATURE;
829
830
831  if (WriteToFile ((void *)&DestMbr, DestFileName)) {
832    printf ("\tsuccessful!\n");
833  }
834
835  return ;
836}
837
838
839int
840main (
841  int argc,
842  char *argv[]
843  )
844{
845  char *SrcImage;
846  char *DstImage;
847  BOOLEAN ForcePatch;    // -f
848  BOOLEAN ProcessMbr;    // -m
849  BOOLEAN DoParse;       // -p SrcImage or -g SrcImage DstImage
850  BOOLEAN Verbose;       // -v
851  UINT64  LogLevel;
852  EFI_STATUS EfiStatus;
853
854  SrcImage = DstImage = NULL;
855  ForcePatch = FALSE;
856  ProcessMbr = FALSE;
857  DoParse    = TRUE;
858  Verbose    = FALSE;
859
860  SetUtilityName ("bootsectimage");
861
862  argc--; argv++;
863
864  if (argc == 0) {
865    Usage ();
866    return -1;
867  }
868
869  while (argc != 0) {
870    if (strcmp (*argv, "-f") == 0 || strcmp (*argv, "--force") == 0) {
871      ForcePatch = TRUE;
872    } else if (strcmp (*argv, "-p") == 0 || strcmp (*argv, "--parse") == 0) {
873      DoParse    = TRUE;
874      argc--; argv++;
875      if (argc < 1) {
876        Usage ();
877        return -1;
878      }
879      SrcImage   = *argv;
880    } else if (strcmp (*argv, "-g") == 0 || strcmp (*argv, "--patch") == 0) {
881      DoParse    = FALSE;
882      argc--; argv++;
883      if (argc < 2) {
884        Usage ();
885        return -1;
886      }
887      SrcImage   = *argv;
888      argc--; argv++;
889      DstImage   = *argv;
890    } else if (strcmp (*argv, "-m") == 0 || strcmp (*argv, "--mbr") == 0) {
891      ProcessMbr = TRUE;
892    } else if (strcmp (*argv, "-v") == 0 || strcmp (*argv, "--verbose") == 0) {
893      Verbose    = TRUE;
894    } else if (strcmp (*argv, "--version") == 0) {
895      Version();
896      return 0;
897    } else if ((stricmp (*argv, "-d") == 0) || (stricmp (*argv, "--debug") == 0)) {
898      argc--; argv++;
899      if (argc < 1) {
900        Usage ();
901        return -1;
902      }
903      EfiStatus = AsciiStringToUint64 (*argv, FALSE, &LogLevel);
904      if (EFI_ERROR (EfiStatus)) {
905        Error (NULL, 0, 1003, "Invalid option value", "%s = %s", "--debug", *argv);
906        return 1;
907      }
908      if (LogLevel > 9) {
909        Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel);
910        return 1;
911      }
912      SetPrintLevel (LogLevel);
913      DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", *argv);
914    } else {
915      Usage ();
916      return -1;
917    }
918
919    argc--; argv++;
920  }
921
922  if (ForcePatch && DoParse) {
923    printf ("ERROR: E1002: Conflicting options: -f, -p. Cannot apply force(-f) to parse(-p)!\n");
924    Usage ();
925    return -1;
926  }
927  if (ForcePatch && !DoParse && ProcessMbr) {
928    printf ("ERROR: E1002: Conflicting options: -f, -g -m. Cannot apply force(-f) to processing MBR (-g -m)!\n");
929    Usage ();
930    return -1;
931  }
932
933  if (Verbose) {
934    SetPrintLevel (VERBOSE_LOG_LEVEL);
935  } else {
936    SetPrintLevel (KEY_LOG_LEVEL);
937  }
938
939  if (DoParse) {
940    if (ProcessMbr) {
941      ParseMbr (SrcImage);
942    } else {
943      ParseBootSector (SrcImage);
944    }
945  } else {
946    if (ProcessMbr) {
947      PatchMbr (DstImage, SrcImage);
948    } else {
949      PatchBootSector (DstImage, SrcImage, ForcePatch);
950    }
951  }
952
953  return 0;
954}
955
956