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