Skip to content

Commit

Permalink
OcBootManagementLib: Add legacy CD boot support
Browse files Browse the repository at this point in the history
  • Loading branch information
Goldfish64 committed Aug 6, 2023
1 parent 52b6eb7 commit a4cb596
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 74 deletions.
3 changes: 2 additions & 1 deletion Include/Acidanthera/Library/OcBootManagementLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ typedef enum OC_LEGACY_BOOT_TYPE_ {
typedef enum OC_LEGACY_OS_TYPE_ {
OcLegacyOsTypeNone,
OcLegacyOsTypeWindowsNtldr,
OcLegacyOsTypeWindowsBootmgr
OcLegacyOsTypeWindowsBootmgr,
OcLegacyOsTypeIsoLinux
} OC_LEGACY_OS_TYPE;

/**
Expand Down
12 changes: 12 additions & 0 deletions Include/Acidanthera/Library/OcFileLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,18 @@ OcPartitionGetDiskHandle (
IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath
);

/**
Check if disk is a CD-ROM device.
@param[in] HdDevicePath The Device Path of the disk.
@retval Device Path or NULL
**/
BOOLEAN
OcIsDiskCdRom (
IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath
);

/**
Locate the disk's EFI System Partition.
Expand Down
11 changes: 7 additions & 4 deletions Library/OcBootManagementLib/BootEntryManagement.c
Original file line number Diff line number Diff line change
Expand Up @@ -1234,11 +1234,14 @@ AddBootEntryFromLegacyPartition (
// External disk = "USB"
// Optical disk = "CD"
//
// TODO: Support optical media.
//
if (BootEntry->IsExternal) {
BootEntry->LoadOptionsSize = L_STR_SIZE ("USB");
BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("USB"), "USB");
if (OcIsDiskCdRom (BootEntry->DevicePath)) {
BootEntry->LoadOptionsSize = L_STR_SIZE ("CD");
BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("CD"), "CD");
} else {
BootEntry->LoadOptionsSize = L_STR_SIZE ("USB");
BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("USB"), "USB");
}
} else {
BootEntry->LoadOptionsSize = L_STR_SIZE ("HD");
BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("HD"), "HD");
Expand Down
132 changes: 78 additions & 54 deletions Library/OcBootManagementLib/LegacyBootSupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,14 @@ CheckLegacySignature (

Offset = 0;

return FindPattern ((CONST UINT8 *)SignatureStr, NULL, (CONST UINT32)AsciiStrLen (SignatureStr), (CONST UINT8 *)Pbr, sizeof (*Pbr), &Offset);
return FindPattern (
(CONST UINT8 *)SignatureStr,
NULL,
(CONST UINT32)AsciiStrLen (SignatureStr),
Pbr->BootStrapCode,
sizeof (Pbr->BootStrapCode),
&Offset
);
}

STATIC
Expand Down Expand Up @@ -166,28 +173,30 @@ InternalLoadAppleLegacyInterface (
// Get device path to disk to be booted.
// TODO: Handle CD booting, device path is not required in that case.
//
WholeDiskPath = OcDiskGetDevicePath (HdDevicePath);
if (WholeDiskPath == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!OcIsDiskCdRom (HdDevicePath)) {
WholeDiskPath = OcDiskGetDevicePath (HdDevicePath);
if (WholeDiskPath == NULL) {
return EFI_INVALID_PARAMETER;
}

DebugPrintDevicePath (DEBUG_INFO, "OCB: Legacy disk device path", WholeDiskPath);
DebugPrintDevicePath (DEBUG_INFO, "OCB: Legacy disk device path", WholeDiskPath);

// TODO: Mark target partition as active on pure MBR and hybrid GPT disks.
// Macs only boot the active partition.
// TODO: Mark target partition as active on pure MBR and hybrid GPT disks.
// Macs only boot the active partition.

//
// Set BootCampHD variable pointing to target disk.
//
Status = gRT->SetVariable (
APPLE_BOOT_CAMP_HD_VARIABLE_NAME,
&gAppleBootVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
GetDevicePathSize (WholeDiskPath),
WholeDiskPath
);
if (EFI_ERROR (Status)) {
return Status;
//
// Set BootCampHD variable pointing to target disk.
//
Status = gRT->SetVariable (
APPLE_BOOT_CAMP_HD_VARIABLE_NAME,
&gAppleBootVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
GetDevicePathSize (WholeDiskPath),
WholeDiskPath
);
if (EFI_ERROR (Status)) {
return Status;
}
}

//
Expand Down Expand Up @@ -242,7 +251,7 @@ InternalGetPartitionLegacyOsType (
{
EFI_STATUS Status;
MASTER_BOOT_RECORD *Mbr;
MASTER_BOOT_RECORD *Pbr;
UINTN MbrSize;
OC_LEGACY_OS_TYPE LegacyOsType;

EFI_DEVICE_PATH_PROTOCOL *DevicePath;
Expand All @@ -258,6 +267,7 @@ InternalGetPartitionLegacyOsType (
if (DevicePath == NULL) {
return OcLegacyOsTypeNone;
}

DebugPrintDevicePath (DEBUG_VERBOSE, "OCB: Reading MBR for disk", DevicePath);

DiskHandle = OcPartitionGetDiskHandle (DevicePath);
Expand All @@ -271,58 +281,72 @@ InternalGetPartitionLegacyOsType (
return OcLegacyOsTypeNone;
}

FreePool (Mbr);

//
// Retrieve the first sector of the partition.
// For hard disk devices, get PBR sector instead.
//
DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading PBR for partition", DevicePath);
Status = OcDiskInitializeContext (
&DiskContext,
PartitionHandle,
TRUE
);
if (EFI_ERROR (Status)) {
return OcLegacyOsTypeNone;
}
if (!OcIsDiskCdRom (DevicePath)) {
FreePool (Mbr);

Pbr = (MASTER_BOOT_RECORD *)AllocatePool (MBR_SIZE);
if (Pbr == NULL) {
DEBUG ((DEBUG_INFO, "OCB: Buffer allocation error\n"));
return OcLegacyOsTypeNone;
}
//
// Retrieve the first sector of the partition.
//
DebugPrintDevicePath (DEBUG_VERBOSE, "OCB: Reading PBR for partition", DevicePath);
Status = OcDiskInitializeContext (
&DiskContext,
PartitionHandle,
TRUE
);
if (EFI_ERROR (Status)) {
return OcLegacyOsTypeNone;
}

Status = OcDiskRead (
&DiskContext,
0,
MBR_SIZE,
Pbr
);
if (EFI_ERROR (Status)) {
FreePool (Pbr);
return OcLegacyOsTypeNone;
MbrSize = ALIGN_VALUE (sizeof (*Mbr), DiskContext.BlockSize);
Mbr = (MASTER_BOOT_RECORD *)AllocatePool (MbrSize);
if (Mbr == NULL) {
DEBUG ((DEBUG_INFO, "OCB: Buffer allocation error\n"));
return OcLegacyOsTypeNone;
}

Status = OcDiskRead (
&DiskContext,
0,
MbrSize,
Mbr
);
if (EFI_ERROR (Status)) {
FreePool (Mbr);
return OcLegacyOsTypeNone;
}
}

DebugPrintHexDump (DEBUG_INFO, "OCB: MbrHEX", Mbr->BootStrapCode, sizeof (Mbr->BootStrapCode));

//
// Validate signature in PBR.
// Validate signature in MBR.
//
if (Pbr->Signature != MBR_SIGNATURE) {
FreePool (Pbr);
if (Mbr->Signature != MBR_SIGNATURE) {
FreePool (Mbr);
return OcLegacyOsTypeNone;
}

//
// Validate sector contents and check for known signatures
// indicating the partition is bootable.
//
LegacyOsType = OcLegacyOsTypeNone;
if (CheckLegacySignature ("BOOTMGR", Pbr)) {
if (CheckLegacySignature ("BOOTMGR", Mbr)) {
LegacyOsType = OcLegacyOsTypeWindowsBootmgr;
} else if (CheckLegacySignature ("NTLDR", Pbr)) {
} else if (CheckLegacySignature ("NTLDR", Mbr)) {
LegacyOsType = OcLegacyOsTypeWindowsNtldr;
} else if ( CheckLegacySignature ("ISOLINUX", Mbr)
|| CheckLegacySignature ("isolinux", Mbr))
{
LegacyOsType = OcLegacyOsTypeIsoLinux;
} else {
LegacyOsType = OcLegacyOsTypeNone;
DEBUG ((DEBUG_INFO, "OCB: Unknown legacy bootsector signature\n"));
}

FreePool (Pbr);
FreePool (Mbr);

return LegacyOsType;
}
15 changes: 14 additions & 1 deletion Library/OcBootManagementLib/PolicyManagement.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ OcGetDevicePolicyType (
SubType = DevicePathSubType (DevicePathWalker);
switch (SubType) {
case MSG_SATA_DP:
//
// Check if this SATA Bus has a CD connected.
//
DevicePathWalker = NextDevicePathNode (DevicePathWalker);
if ( !IsDevicePathEnd (DevicePathWalker)
&& (DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH)
&& (DevicePathSubType (DevicePathWalker) == MEDIA_CDROM_DP))
{
if (External != NULL) {
*External = TRUE;
}
}

return OC_SCAN_ALLOW_DEVICE_SATA;
case MSG_SASEX_DP:
return OC_SCAN_ALLOW_DEVICE_SASEX;
Expand Down Expand Up @@ -342,7 +355,7 @@ OcGetBootDevicePathType (
// Certain Mac models lock up if any additional probing of the device path
// is performed when the Apple legacy loader interface is being started.
//
if (DevicePath->Type == MEDIA_DEVICE_PATH && DevicePath->SubType == MEDIA_PIWG_FW_FILE_DP) {
if ((DevicePath->Type == MEDIA_DEVICE_PATH) && (DevicePath->SubType == MEDIA_PIWG_FW_FILE_DP)) {
return OC_BOOT_UNKNOWN;
}

Expand Down
69 changes: 55 additions & 14 deletions Library/OcFileLib/DiskMisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,21 +241,28 @@ OcDiskGetDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL *PrefixPath;
EFI_DEVICE_PATH_PROTOCOL *TempPath;
CONST HARDDRIVE_DEVICE_PATH *HdNode;
EFI_DEVICE_PATH_PROTOCOL *PrefixPath;
EFI_DEVICE_PATH_PROTOCOL *TempPath;
CONST EFI_DEVICE_PATH_PROTOCOL *HdNode;

ASSERT (HdDevicePath != NULL);

HdNode = (HARDDRIVE_DEVICE_PATH *)(
FindDevicePathNodeWithType (
HdDevicePath,
MEDIA_DEVICE_PATH,
MEDIA_HARDDRIVE_DP
)
);
HdNode = FindDevicePathNodeWithType (
HdDevicePath,
MEDIA_DEVICE_PATH,
MEDIA_HARDDRIVE_DP
);
if (HdNode == NULL) {
return NULL;
HdNode = FindDevicePathNodeWithType (
HdDevicePath,
MEDIA_DEVICE_PATH,
MEDIA_CDROM_DP
);
if (HdNode == NULL) {
return NULL;
}

DEBUG ((DEBUG_INFO, "got cdrom\n"));
}

PrefixPath = DuplicateDevicePath (HdDevicePath);
Expand Down Expand Up @@ -298,6 +305,29 @@ OcPartitionGetDiskHandle (
);
}

BOOLEAN
OcIsDiskCdRom (
IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;

ASSERT (DiskDevicePath != NULL);

DevicePathWalker = DiskDevicePath;
while (!IsDevicePathEnd (DevicePathWalker)) {
if ( (DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH)
&& (DevicePathSubType (DevicePathWalker) == MEDIA_CDROM_DP))
{
return TRUE;
}

DevicePathWalker = NextDevicePathNode (DevicePathWalker);
}

return FALSE;
}

EFI_DEVICE_PATH_PROTOCOL *
OcDiskFindSystemPartitionPath (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath,
Expand Down Expand Up @@ -676,6 +706,7 @@ OcGetDiskMbrTable (
{
EFI_STATUS Status;
MASTER_BOOT_RECORD *Mbr;
UINTN MbrSize;
OC_DISK_CONTEXT DiskContext;
UINTN Index;
BOOLEAN IsProtectiveMbr;
Expand All @@ -685,17 +716,27 @@ OcGetDiskMbrTable (
//
// Read first sector containing MBR table.
//
Status = OcDiskInitializeContext (&DiskContext, DiskHandle, UseBlockIo2);
Status = OcDiskInitializeContext (
&DiskContext,
DiskHandle,
UseBlockIo2
);
if (EFI_ERROR (Status)) {
return NULL;
}

Mbr = (MASTER_BOOT_RECORD *)AllocatePool (sizeof (*Mbr));
MbrSize = ALIGN_VALUE (sizeof (*Mbr), DiskContext.BlockSize);
Mbr = (MASTER_BOOT_RECORD *)AllocatePool (MbrSize);
if (Mbr == NULL) {
return NULL;
}

Status = OcDiskRead (&DiskContext, 0, sizeof (*Mbr), Mbr);
Status = OcDiskRead (
&DiskContext,
0,
MbrSize,
Mbr
);
if (EFI_ERROR (Status)) {
FreePool (Mbr);
return NULL;
Expand Down

0 comments on commit a4cb596

Please sign in to comment.