GenBootSector.c revision 4fd606d1f5abe38e1f42c38de1d2e895166bd0f4
/** @file
Copyright (c) 2006 - 2010, 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
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Abstract:
NOTE:
If we write MBR to disk, we just update the MBR code and the partition table wouldn't be over written.
If we process DBR, we will patch MBR to set first partition active if no active partition exists.
**/
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <Common/UefiBaseTypes.h>
#include "ParseInf.h"
#include "EfiUtilityMsgs.h"
#include "CommonLib.h"
//
// Utility Name
//
#define UTILITY_NAME "GenBootSector"
//
// Utility version information
//
#define UTILITY_MAJOR_VERSION 0
#define UTILITY_MINOR_VERSION 1
#define MAX_DRIVE 26
#define PARTITION_TABLE_OFFSET 0x1BE
#define SIZE_OF_PARTITION_ENTRY 0x10
#define PARTITION_ENTRY_STARTLBA_OFFSET 8
#define PARTITION_ENTRY_NUM 4
);
typedef enum {
PatchTypeFileImage // input and output are all file image, patching action is same as PatchTypeFloppy
} PATCH_TYPE;
typedef enum {
} PATH_TYPE;
typedef enum {
} ERROR_STATUS;
CHAR *ErrorStatusDesc[] = {
"Success",
"Failed to create files",
"No MBR exists",
"Failed to detect Fat type",
"Inavlid path"
};
typedef struct _DRIVE_TYPE_DESC {
#define DRIVE_TYPE_ITEM(x) {x, #x}
DRIVE_TYPE_DESC DriveTypeDesc[] = {
};
typedef struct _DRIVE_INFO {
} DRIVE_INFO;
typedef struct _PATH_INFO {
} PATH_INFO;
#define BOOT_SECTOR_LBA_OFFSET 0x1FA
)
/*++
Routine Description:
Get drive information including disk number and drive type,
NOTE: Floppy disk doesn't have disk number but it doesn't matter because
Arguments:
VolumeLetter : volume letter, e.g.: C for C:, A for A:
DriveInfo : pointer to DRIVE_INFO structure receiving drive information.
Return:
TRUE : successful
FALSE : failed
--*/
{
return FALSE;
}
0,
NULL,
0,
);
if (VolumeHandle == INVALID_HANDLE_VALUE) {
fprintf (
"error E0005: CreateFile failed: Volume = %s, LastError = 0x%x\n",
GetLastError ()
);
return FALSE;
}
//
// Get Disk Number. It should fail when operating on floppy. That's ok
// because Disk Number is only needed when operating on Hard or USB disk.
//
// To direct write to disk:
// for USB and HD: use path = \\.\PHYSICALDRIVEx, where x is Disk Number
// for floppy: use path = \\.\X:, where X can be A or B
//
NULL,
0,
sizeof(StorageDeviceNumber),
);
//
// DeviceIoControl should fail if Volume is floppy or network drive.
//
if (!Success) {
//
// Only care about the disk.
//
return FALSE;
} else{
}
//
// Fill in the type string
//
break;
}
}
//
// Should have a type.
//
return FALSE;
}
return TRUE;
}
)
/*++
Routine Description:
List every drive in current system and their information.
--*/
{
if (Index < 2) {
// Floppy will occupy 'A' and 'B'
fprintf (
"%c: - Type: %s\n",
);
} else {
fprintf (
"%c: - DiskNum: %u, Type: %s\n",
(unsigned) DriveInfo.DiskNumber,
);
}
}
}
}
}
)
/*++
Description:
Get the offset of boot sector.
For non-MBR disk, offset is just 0
for disk with MBR, offset needs to be caculated by parsing MBR
NOTE: if no one is active, we will patch MBR to select first partition as active.
Arguments:
DiskHandle : HANDLE of disk
PathInfo : PATH_INFO structure.
WriteToDisk : TRUE indicates writing
Return:
-1 : failed
o.w. : Offset to boot sector
--*/
{
DbrOffset = 0;
return -1;
}
//
// Check Signature, Jmp, and Boot Indicator.
// if all pass, we assume MBR found.
//
// Check Signature: 55AA
// Check Jmp: (EB ?? 90) or (E9 ?? ??)
(DiskPartition[0] != 0xE9)) {
// Check Boot Indicator: 0x00 or 0x80
// Boot Indicator is the first byte of Partition Entry
break;
}
}
}
}
if (HasMbr) {
//
// Skip MBR
//
//
// Found Boot Indicator.
//
DbrOffset = *(DWORD *)&DiskPartition[PARTITION_TABLE_OFFSET + (Index * SIZE_OF_PARTITION_ENTRY) + PARTITION_ENTRY_STARTLBA_OFFSET];
break;
}
}
//
// If no boot indicator, we manually select 1st partition, and patch MBR.
//
if (Index == PARTITION_ENTRY_NUM) {
}
}
}
return DbrOffset;
}
/**
*
* @param PathInfo
* @param ProcessMbr
* @param FileHandle
*
* @return ERROR_STATUS
*/
)
{
}
*FileHandle = CreateFile(
NULL,
);
if (*FileHandle == INVALID_HANDLE_VALUE) {
return ErrorFileCreate;
}
if (!ProcessMbr) {
//
// 1. Process boot sector, set file pointer to the beginning of boot sector
//
} else if(*DbrOffset == 0) {
//
// If user want to process Mbr, but no Mbr exists, simply return FALSE
//
return ErrorNoMbr;
} else {
//
// 2. Process MBR, set file pointer to 0
//
}
}
return ErrorSuccess;
}
/**
Writing or reading boot sector or MBR according to the argument.
@param InputInfo PATH_INFO instance for input path
@param OutputInfo PATH_INFO instance for output path
@param ProcessMbr TRUE is to process MBR, otherwise, processing boot sector
@return ERROR_STATUS
**/
)
{
//
// Create file Handle and move file Pointer is pointed to beginning of Mbr or Dbr
//
if (Status != ErrorSuccess) {
return Status;
}
//
// Create file Handle and move file Pointer is pointed to beginning of Mbr or Dbr
//
if (Status != ErrorSuccess) {
return Status;
}
//
//
return ErrorFileReadWrite;
}
// Manually set BS_DrvNum to 0x80 as window's format.exe has a bug which will clear this field discarding USB disk's MBR.
// offset of BS_DrvNum is 0x24 for FAT12/16
// 0x40 for FAT32
//
if (DrvNumOffset == -1) {
return ErrorFatType;
}
//
// Some legacy BIOS require 0x80 discarding MBR.
// Question left here: is it needed to check Mbr before set 0x80?
//
}
//
// Patch LBAOffsetForBootSector
//
}
if (ProcessMbr) {
//
// Use original partition table
//
return ErrorFileReadWrite;
}
}
}
//
//
return ErrorFileReadWrite;
}
return ErrorSuccess;
}
void
Version (
void
)
/*++
Routine Description:
Displays the standard utility information to SDTOUT
Arguments:
None
Returns:
None
--*/
{
printf ("%s v%d.%d %s -Utility to retrieve and update the boot sector or MBR.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
printf ("Copyright (c) 2009 - 2010 Intel Corporation. All rights reserved.\n");
}
void
)
{
Version();
printf ("\nUsage: \n\
GenBootSector\n\
[-l, --list list disks]\n\
[-i, --input Filename]\n\
[-o, --output Filename]\n\
[-m, --mbr process the MBR also]\n\
[-v, --verbose]\n\
[--version]\n\
[-q, --quiet disable all messages except fatal errors]\n\
[-d, --debug[#]\n\
[-h, --help]\n");
}
/**
Get path information, including physical path for windows platform.
@param PathInfo Point to PATH_INFO structure.
@return whether path is valid.
**/
)
{
FILE *f;
//
// If path is disk path
//
return ErrorSuccess;
}
return ErrorPath;
}
return ErrorPath;
}
} else {
return ErrorPath;
}
return ErrorSuccess;
}
//
// If path is file path, check whether file is valid.
//
if (f == NULL) {
return ErrorPath;
}
}
return ErrorSuccess;
}
main (
)
{
PATH_INFO InputPathInfo = {0};
PATH_INFO OutputPathInfo = {0};
argv ++;
argc --;
ProcessMbr = FALSE;
if (argc == 0) {
PrintUsage();
return 0;
}
//
// Parse command line
//
ListDrive ();
return 0;
}
ProcessMbr = TRUE;
continue;
}
return 1;
}
return 1;
}
++Index;
continue;
}
return 1;
}
return 1;
}
++Index;
continue;
}
PrintUsage ();
return 0;
}
Version ();
return 0;
}
continue;
}
continue;
}
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;
}
++Index;
continue;
}
//
// Don't recognize the parameter.
//
return 1;
}
return 1;
}
return 1;
}
return 1;
}
return 1;
}
//
// Process DBR (Patch or Read)
//
if (Status == ErrorSuccess) {
fprintf (
"%s %s: successful!\n",
);
return 0;
} else {
fprintf (
"%s: %s %s: failed - %s (LastError: 0x%x)!\n",
GetLastError ()
);
return 1;
}
}