Author: ion Date: Tue Jan 19 18:21:54 2016 New Revision: 70618 URL: http://svn.reactos.org/svn/reactos?rev=70618&view=rev Log: [BOOTMGR]: Support for launching a recovery sequence. [BOOTMGR]: Stub support for boot errors. [BOOTMGR]: Stubplement support for device creation for boot applications (only for fully specified devices) [BOOTMGR]: Implement support for execution transfer, including recovery mode/sequence. [BOOTMGR]: Implement support for launching a boot entry. [BOOTLIB]: Support for EFI Firmware device enumeration, driver attachment, and comparison. [BOOTLIB]: Support for appending BOOLEAN or INTEGER BCD options. Next step is the PE loader.
Modified: trunk/reactos/boot/environ/app/bootmgr/bootmgr.c trunk/reactos/boot/environ/include/bcd.h trunk/reactos/boot/environ/include/bl.h trunk/reactos/boot/environ/lib/firmware/efi/firmware.c trunk/reactos/boot/environ/lib/io/device.c trunk/reactos/boot/environ/lib/misc/bcdopt.c Modified: trunk/reactos/boot/environ/app/bootmgr/bootmgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/app/bootmgr/bootmgr.c?rev=70618&r1=70617&r2=70618&view=diff ============================================================================== --- trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] Tue Jan 19 18:21:54 2016 @@ -1,7 +1,7 @@ /* * COPYRIGHT: See COPYING.ARM in the top level directory * PROJECT: ReactOS UEFI Boot Manager - * FILE: boot/environ/app/bootmgr/bootmgr.c + * FILE: boot/environ/app/bootmgr/bootmgr.cla * PURPOSE: Boot Manager Entrypoint * PROGRAMMER: Alex Ionescu (alex.ione...@reactos.org) */ @@ -2033,13 +2033,562 @@ BmpLaunchBootEntry ( _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, _Out_ PULONG EntryIndex, - _In_ ULONG Unknown, + _In_ ULONG LaunchCode, _In_ BOOLEAN LaunchWinRe - ) -{ - EfiPrintf(L"Boot launch not yet implemented\r\n"); - EfiStall(1000000000); + ); + +NTSTATUS +BmLaunchRecoverySequence ( + _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, + _In_ ULONG LaunchCode + ) +{ + NTSTATUS Status; + PBL_LOADED_APPLICATION_ENTRY RecoveryEntry; + HANDLE BcdHandle; + PGUID RecoverySequence; + ULONG Count, i, RecoveryIndex, SequenceCount; + PBL_LOADED_APPLICATION_ENTRY* Sequence; + + RecoveryIndex = 0; + Sequence = NULL; + RecoverySequence = NULL; + Count = 0; + BcdHandle = NULL; + + Status = BmOpenDataStore(&BcdHandle); + if (NT_SUCCESS(Status)) + { + Status = BlGetBootOptionGuidList(BootEntry->BcdData, + BcdLibraryObjectList_RecoverySequence, + &RecoverySequence, + &SequenceCount); + if (NT_SUCCESS(Status)) + { + Status = BmGetBootSequence(BcdHandle, + RecoverySequence, + SequenceCount, + BL_APPLICATION_ENTRY_RECOVERY, + &Sequence, + &Count); + if (NT_SUCCESS(Status)) + { + if (BcdHandle) + { + BmCloseDataStore(BcdHandle); + } + + for (i = 0; i < Count; ++i) + { + if (LaunchCode == 2 || LaunchCode == 5) + { + BlRemoveBootOption(Sequence[i]->BcdData, BcdLibraryInteger_DisplayMessageOverride); + BlAppendBootOptionInteger(Sequence[i], + BcdLibraryInteger_DisplayMessageOverride, + 4); + } + else if (LaunchCode == 3) + { + BlRemoveBootOption(Sequence[i]->BcdData, BcdLibraryInteger_DisplayMessageOverride); + BlAppendBootOptionInteger(Sequence[i], + BcdLibraryInteger_DisplayMessageOverride, + 10); + } + + Status = BmpLaunchBootEntry(Sequence[i], NULL, LaunchCode, FALSE); + if (!NT_SUCCESS(Status)) + { + break; + } + } + } + + if (Sequence) + { + for (RecoveryIndex = 0; RecoveryIndex < Count; RecoveryIndex++) + { + RecoveryEntry = Sequence[RecoveryIndex]; + if (RecoveryEntry) + { + BlDestroyBootEntry(RecoveryEntry); + } + } + BlMmFreeHeap(Sequence); + } + } + + if (RecoverySequence) + { + BlMmFreeHeap(RecoverySequence); + } + } + + return Status; +} + +ULONG +BmDisplayDumpError ( + _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, + _In_ ULONG LaunchCode + ) +{ + ULONG BootError; + NTSTATUS Status; + BOOLEAN Restart, NoError; + + BootError = 1; + + Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData, + BcdLibraryBoolean_RestartOnFailure, + &Restart); + if ((NT_SUCCESS(Status)) && (Restart)) + { + return BootError; + } + + Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData, + BcdBootMgrBoolean_NoErrorDisplay, + &NoError); + if ((NT_SUCCESS(Status)) && (NoError)) + { + return BootError; + } + + if (BmpInternalBootError) + { + return (ULONG)BmpInternalBootError; // ??? + } + + EfiPrintf(L"Error menu not yet implemented\r\n"); + return BootError; +} + +NTSTATUS +BmpCreateDevices ( + _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry + ) +{ + ULONG NextOffset, DataOffset, ListOffset; + PBL_BCD_OPTION Option, ListOption; + BcdElementType ElementType; + PBCD_DEVICE_OPTION BcdDevice; + + NextOffset = 0; + do + { + Option = (PBL_BCD_OPTION)((ULONG_PTR)BootEntry->BcdData + NextOffset); + NextOffset = Option->NextEntryOffset; + + if (Option->Empty) + { + continue; + } + + ElementType.PackedValue = Option->Type; + if (ElementType.Format != BCD_TYPE_DEVICE) + { + continue; + } + + DataOffset = Option->DataOffset; + + BcdDevice = (PBCD_DEVICE_OPTION)((ULONG_PTR)BootEntry->BcdData + DataOffset); + if (!(BcdDevice->DeviceDescriptor.Flags & 1)) + { + continue; + } + + ListOption = NULL; + ListOffset = Option->ListOffset; + if (Option->ListOffset) + { + ListOption = (PBL_BCD_OPTION)((ULONG_PTR)BootEntry->BcdData + ListOffset); + } + + EfiPrintf(L"Unspecified devices not yet supported: %p\r\n", ListOption); + return STATUS_NOT_SUPPORTED; + } while (NextOffset != 0); + + return STATUS_SUCCESS; +} + +/* MOVE TO IMAGe.C */ +NTSTATUS +BlImgLoadBootApplication ( + _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, + _Out_ PHANDLE AppHandle + ) +{ + EfiPrintf(L"Loading application %p\r\n", BootEntry); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +BlImgStartBootApplication ( + _In_ HANDLE AppHandle, + _Inout_ PBL_RETURN_ARGUMENTS ReturnArguments + ) +{ + EfiPrintf(L"Starting application %p\r\n", AppHandle); + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +BlImgUnloadBootApplication ( + _In_ HANDLE AppHandle + ) +{ + EfiPrintf(L"Unloading application %p\r\n", AppHandle); + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +BmpTransferExecution ( + _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, + _Out_ PULONG LaunchCode, + _Out_ PBOOLEAN Recover + ) +{ + PWCHAR AppPath; + NTSTATUS Status; + PBL_DEVICE_DESCRIPTOR AppDevice; + BL_RETURN_ARGUMENTS ReturnArgs; + BOOLEAN AdvancedOptions; + HANDLE AppHandle; + + Status = BlGetBootOptionString(BootEntry->BcdData, + BcdLibraryString_ApplicationPath, + &AppPath); + if (!NT_SUCCESS(Status)) + { + AppPath = NULL; + } + + if (BootEntry->Flags & BL_APPLICATION_ENTRY_STARTUP) + { +#if BL_NET_SUPPORT + Status = BlNetSoftReboot(BootEntry); +#else + EfiPrintf(L"Net boot not supported\r\n"); + Status = STATUS_NOT_SUPPORTED; +#endif + goto Quickie; + } + + do + { + Status = BlImgLoadBootApplication(BootEntry, &AppHandle); + if (Status == STATUS_NOT_FOUND) + { + Status = BlGetBootOptionDevice(BootEntry->BcdData, + BcdLibraryDevice_ApplicationDevice, + &AppDevice, + NULL); + if (NT_SUCCESS(Status)) + { + Status = BlFwEnumerateDevice(AppDevice); + } + + if (!NT_SUCCESS(Status)) + { + BmFatalErrorEx(2, (ULONG_PTR)AppPath, Status, 0, 0); + goto Quickie; + } + + Status = BlImgLoadBootApplication(BootEntry, &AppHandle); + } + + if (Status == STATUS_CANCELLED) + { + if ((BmGetBootMenuPolicy(BootEntry) != MenuPolicyStandard) || + !(MiscGetBootOption(BootEntry->BcdData, + BcdLibraryObjectList_RecoverySequence))) + { + goto Quickie; + } + + *LaunchCode = 4; + *Recover = TRUE; + goto Quickie; + } + + if (Status == 0xC0210000) + { + *LaunchCode = 4; + *Recover = TRUE; + goto Quickie; + } + + if (!NT_SUCCESS(Status)) + { + BmFatalErrorEx(2, (ULONG_PTR)AppPath, Status, 0, 0); + goto Quickie; + } + + RtlZeroMemory(&ReturnArgs, sizeof(ReturnArgs)); + //BmpLogApplicationLaunchEvent(&BootEntry->Guid, AppPath); + + Status = BlImgStartBootApplication(AppHandle, &ReturnArgs); + +#if BL_BITLOCKER_SUPPORT + BlFveSecureBootCheckpointAppReturn(BootEntry, &ReturnArgs); +#endif + + //BlBsdLogEntry(1, 0x12, &BootEntry->Guid, 0x14); + + BlImgUnloadBootApplication(AppHandle); + + } while (Status != 0xC0000453); + + *Recover = TRUE; + if (ReturnArgs.Flags & 1) + { + Status = BlGetBootOptionBoolean(BootEntry->BcdData, + BcdLibraryBoolean_DisplayAdvancedOptions, + &AdvancedOptions); + if ((NT_SUCCESS(Status)) && (AdvancedOptions)) + { + *LaunchCode = 2; + } + else + { + *LaunchCode = 1; + } + } + else if (ReturnArgs.Flags & 4) + { + *LaunchCode = 1; + } + else if (ReturnArgs.Flags & 8) + { + *LaunchCode = 5; + } + else if (ReturnArgs.Flags & 0x10) + { + *LaunchCode = 6; + } + else if (ReturnArgs.Flags & 0x20) + { + *LaunchCode = 7; + } + else if (ReturnArgs.Flags & 0x40) + { + *Recover = FALSE; + BmFatalErrorEx(11, Status, 0, 0, 0); + } + +Quickie: + if (AppPath) + { + BlMmFreeHeap(AppPath); + } + + return Status; +} + +NTSTATUS +BmpLaunchBootEntry ( + _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, + _Out_ PULONG EntryIndex, + _In_ ULONG LaunchCode, + _In_ BOOLEAN LaunchWinRe + ) +{ + HANDLE BcdHandle; + NTSTATUS Status; + GUID ObjectId; + BOOLEAN DoRecovery, AutoRecovery, DoRestart, RestartOnFailure; + ULONG ErrorCode; + BOOLEAN AdvancedOneTime, EditOneTime, Recover; + + if (BootEntry->Flags & BL_APPLICATION_ENTRY_WINLOAD) + { + if (MiscGetBootOption(BootEntry->BcdData, BcdOSLoaderBoolean_AdvancedOptionsOneTime)) + { + BcdHandle = NULL; + Status = BmOpenDataStore(BcdHandle); + if (NT_SUCCESS(Status)) + { + ObjectId = BootEntry->Guid; + BmPurgeOption(BcdHandle, &ObjectId, BcdOSLoaderBoolean_AdvancedOptionsOneTime); + BmCloseDataStore(BcdHandle); + } + } + if (MiscGetBootOption(BootEntry->BcdData, BcdOSLoaderBoolean_OptionsEditOneTime)) + { + BcdHandle = NULL; + Status = BmOpenDataStore(BcdHandle); + if (NT_SUCCESS(Status)) + { + ObjectId = BootEntry->Guid; + BmPurgeOption(BcdHandle, &ObjectId, BcdOSLoaderBoolean_OptionsEditOneTime); + BmCloseDataStore(BcdHandle); + } + } + } + +TryAgain: + DoRecovery = FALSE; + Recover = FALSE; + BmpSelectedBootEntry = BootEntry; + + Status = BmpCreateDevices(BootEntry); + if (!NT_SUCCESS(Status)) + { + if (!LaunchWinRe) + { + return Status; + } + + LaunchCode = 2; + goto Quickie; + } + + if (BootEntry->Flags & BL_APPLICATION_ENTRY_WINLOAD) + { + Status = BlGetBootOptionBoolean(BootEntry->BcdData, BcdOSLoaderBoolean_AdvancedOptionsOneTime, &AdvancedOneTime); + if (NT_SUCCESS(Status)) + { + if (AdvancedOneTime) + { + BlAppendBootOptionBoolean(BootEntry, BcdLibraryBoolean_DisplayAdvancedOptions); + } + else + { + BlRemoveBootOption(BootEntry->BcdData, BcdLibraryBoolean_DisplayAdvancedOptions); + } + + BlRemoveBootOption(BootEntry->BcdData, BcdOSLoaderBoolean_AdvancedOptionsOneTime); + } + + Status = BlGetBootOptionBoolean(BootEntry->BcdData, BcdOSLoaderBoolean_OptionsEditOneTime, &EditOneTime); + if (NT_SUCCESS(Status)) + { + if (AdvancedOneTime) + { + BlAppendBootOptionBoolean(BootEntry, BcdLibraryBoolean_DisplayOptionsEdit); + } + else + { + BlRemoveBootOption(BootEntry->BcdData, BcdLibraryBoolean_DisplayOptionsEdit); + } + + BlRemoveBootOption(BootEntry->BcdData, BcdOSLoaderBoolean_OptionsEditOneTime); + } + } + + Status = BmpTransferExecution(BootEntry, &LaunchCode, &Recover); + if (!LaunchWinRe) + { + return Status; + } + + DoRecovery = Recover; + + if (((NT_SUCCESS(Status)) || (Status == STATUS_CANCELLED)) && !(Recover)) + { + return Status; + } + + if (!Recover) + { + LaunchCode = 2; + goto Quickie; + } + +Quickie: + if (MiscGetBootOption(BootEntry->BcdData, BcdLibraryObjectList_RecoverySequence)) + { + if ((LaunchCode == 3) || (LaunchCode == 5) || (LaunchCode == 6)) + { + Status = BlGetBootOptionBoolean(BootEntry->BcdData, BcdLibraryBoolean_AutoRecoveryEnabled, &AutoRecovery); + if (NT_SUCCESS(Status)) + { + DoRecovery = AutoRecovery; + } + } + } + else + { + DoRecovery = FALSE; + } + + RestartOnFailure = FALSE; + BlGetBootOptionBoolean(BlpApplicationEntry.BcdData, BcdLibraryBoolean_RestartOnFailure, &RestartOnFailure); + DoRestart = RestartOnFailure ? FALSE : DoRecovery; + while (1) + { + if (DoRestart) + { + if (AutoRecovery) + { + //BlFveRegisterBootEntryForTrustedWimBoot(BootEntry, TRUE); + } + + Status = BmLaunchRecoverySequence(BootEntry, LaunchCode); + + if (AutoRecovery) + { + //BlFveRegisterBootEntryForTrustedWimBoot(BootEntry, FALSE); + AutoRecovery = FALSE; + } + + if (NT_SUCCESS(Status)) + { + return STATUS_SUCCESS; + } + + BlRemoveBootOption(BootEntry->BcdData, BcdLibraryObjectList_RecoverySequence); + } + + if (!BmpInternalBootError) + { + BmFatalErrorEx(4, Status, 0, 0, 0); + } + + ErrorCode = BmDisplayDumpError(BootEntry, LaunchCode); + BmErrorPurge(); + + switch (ErrorCode) + { + case 6: + goto TryAgain; + case 5: + break; + case 4: + return STATUS_CANCELLED; + case 3: + Status = BmOpenDataStore(BcdHandle); + if (NT_SUCCESS(Status)) + { + Status = BmProcessCustomAction(BcdHandle, NULL); + } + if (BcdHandle) + { + BmCloseDataStore(BcdHandle); + } + return Status; + case 7: + BlAppendBootOptionBoolean(BootEntry, BcdOSLoaderBoolean_AdvancedOptionsOneTime); + goto TryAgain; + case 8: + BlAppendBootOptionBoolean(BootEntry, BcdOSLoaderBoolean_OptionsEditOneTime); + goto TryAgain; + case 2: + DoRestart = TRUE; + LaunchCode = 1; + goto TryAgain; + default: + return STATUS_CANCELLED; + } + } + + + + return STATUS_SUCCESS; } /*++ Modified: trunk/reactos/boot/environ/include/bcd.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bcd.h?rev=70618&r1=70617&r2=70618&view=diff ============================================================================== --- trunk/reactos/boot/environ/include/bcd.h [iso-8859-1] (original) +++ trunk/reactos/boot/environ/include/bcd.h [iso-8859-1] Tue Jan 19 18:21:54 2016 @@ -92,6 +92,8 @@ BcdLibraryInteger_FveBandId = 0x1500004C, BcdLibraryBoolean_ConsoleExtendedInput = 0x16000050, BcdLibraryInteger_GraphicsResolution = 0x15000052, + BcdLibraryInteger_DisplayMessage = 0x15000065, /* Undocumented */ + BcdLibraryInteger_DisplayMessageOverride = 0x15000066, /* Undocumented */ BcdLibraryBoolean_RestartOnFailure = 0x16000053, BcdLibraryBoolean_GraphicsForceHighestMode = 0x16000054, BcdLibraryBoolean_IsolatedExecutionContext = 0x16000060, @@ -151,6 +153,7 @@ BcdOSLoaderInteger_DriverLoadFailurePolicy = 0x250000c1, BcdOSLoaderInteger_BootMenuPolicy = 0x250000C2, BcdOSLoaderBoolean_AdvancedOptionsOneTime = 0x260000C3, + BcdOSLoaderBoolean_OptionsEditOneTime = 0x260000C4, /* Undocumented */ BcdOSLoaderInteger_BootStatusPolicy = 0x250000E0, BcdOSLoaderBoolean_DisableElamDrivers = 0x260000E1, BcdOSLoaderInteger_HypervisorLaunchType = 0x250000F0, Modified: trunk/reactos/boot/environ/include/bl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bl.h?rev=70618&r1=70617&r2=70618&view=diff ============================================================================== --- trunk/reactos/boot/environ/include/bl.h [iso-8859-1] (original) +++ trunk/reactos/boot/environ/include/bl.h [iso-8859-1] Tue Jan 19 18:21:54 2016 @@ -77,6 +77,7 @@ #define BL_APPLICATION_ENTRY_BOOTMGR 0x1000 #define BL_APPLICATION_ENTRY_DISPLAY_ORDER 0x800000 #define BL_APPLICATION_ENTRY_FIXED_SEQUENCE 0x20000000 +#define BL_APPLICATION_ENTRY_RECOVERY 0x40000000 #define BL_CONTEXT_PAGING_ON 1 #define BL_CONTEXT_INTERRUPTS_ON 2 @@ -110,6 +111,8 @@ #define BL_FS_REGISTER_AT_HEAD_FLAG 1 #define BL_BLOCK_DEVICE_REMOVABLE_FLAG 0x01 +#define BL_BLOCK_DEVICE_PRESENT_FLAG 0x02 +#define BL_BLOCK_DEVICE_VIRTUAL_FLAG 0x04 #define BL_MEMORY_CLASS_SHIFT 28 @@ -685,7 +688,9 @@ { ULONG Version; NTSTATUS Status; - ULONG ReturnArgumentData[5]; + ULONG Flags; + ULONGLONG DataSize; + ULONGLONG DataPage; } BL_RETURN_ARGUMENTS, *PBL_RETURN_ARGUMENTS; typedef struct _BL_MEMORY_DESCRIPTOR @@ -794,8 +799,10 @@ LARGE_INTEGER ImageSize; ULONG ImageOffset; } RamDisk; + + ULONG File; // unknown for now }; -} BL_LOCAL_DEVICE; +} BL_LOCAL_DEVICE, *PBL_LOCAL_DEVICE; typedef struct _BL_DEVICE_DESCRIPTOR { @@ -1317,6 +1324,11 @@ ); NTSTATUS +BlFwEnumerateDevice ( + _In_ PBL_DEVICE_DESCRIPTOR Device + ); + +NTSTATUS EfiAllocatePages ( _In_ ULONG Type, _In_ ULONG Pages, @@ -1774,6 +1786,19 @@ BlCopyBootOptions ( _In_ PBL_BCD_OPTION OptionList, _Out_ PBL_BCD_OPTION *CopiedOptions + ); + +NTSTATUS +BlAppendBootOptionBoolean ( + _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, + _In_ ULONG OptionId + ); + +NTSTATUS +BlAppendBootOptionInteger ( + _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, + _In_ ULONG OptionId, + _In_ ULONGLONG Value ); NTSTATUS @@ -2140,6 +2165,14 @@ _In_ PWCHAR FileName, _In_ ULONG Flags, _Out_ PULONG FileId + ); + +/* BLOCK I/O ROUTINES *******************************************************/ + +NTSTATUS +BlockIoEfiCompareDevice ( + _In_ PBL_DEVICE_DESCRIPTOR Device, + _In_ EFI_HANDLE Handle ); /* INPUT CONSOLE ROUTINES ****************************************************/ Modified: trunk/reactos/boot/environ/lib/firmware/efi/firmware.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/firmware/efi/firmware.c?rev=70618&r1=70617&r2=70618&view=diff ============================================================================== --- trunk/reactos/boot/environ/lib/firmware/efi/firmware.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/firmware/efi/firmware.c [iso-8859-1] Tue Jan 19 18:21:54 2016 @@ -1047,6 +1047,42 @@ /* Call the EFI runtime */ EfiRT->ResetSystem(ResetType, EFI_SUCCESS, 0, NULL); +} + +NTSTATUS +EfiConnectController ( + _In_ EFI_HANDLE ControllerHandle + ) +{ + BL_ARCH_MODE OldMode; + EFI_STATUS EfiStatus; + + /* Is this EFI 1.02? */ + if (EfiST->Hdr.Revision == EFI_1_02_SYSTEM_TABLE_REVISION) + { + /* This function didn't exist back then */ + return STATUS_NOT_SUPPORTED; + } + + /* Are we in protected mode? */ + OldMode = CurrentExecutionContext->Mode; + if (OldMode != BlRealMode) + { + /* FIXME: Not yet implemented */ + return STATUS_NOT_IMPLEMENTED; + } + + /* Make the EFI call */ + EfiStatus = EfiBS->ConnectController(ControllerHandle, NULL, NULL, TRUE); + + /* Switch back to protected mode if we came from there */ + if (OldMode != BlRealMode) + { + BlpArchSwitchContext(OldMode); + } + + /* Convert the error to an NTSTATUS */ + return EfiGetNtStatusCode(EfiStatus); } NTSTATUS @@ -1748,6 +1784,91 @@ return Status; } +NTSTATUS +BlFwEnumerateDevice ( + _In_ PBL_DEVICE_DESCRIPTOR Device + ) +{ + NTSTATUS Status; + ULONG PathProtocols, BlockProtocols; + EFI_HANDLE* PathArray; + EFI_HANDLE* BlockArray; + + /* Initialize locals */ + BlockArray = NULL; + PathArray = NULL; + PathProtocols = 0; + BlockProtocols = 0; + + /* Enumeration only makes sense on disks or partitions */ + if ((Device->DeviceType != DiskDevice) && + (Device->DeviceType != LegacyPartitionDevice) && + (Device->DeviceType != PartitionDevice)) + { + return STATUS_NOT_SUPPORTED; + } + + /* Enumerate the list of device paths */ + Status = EfiLocateHandleBuffer(ByProtocol, + &EfiDevicePathProtocol, + &PathProtocols, + &PathArray); + if (NT_SUCCESS(Status)) + { + /* Loop through each one */ + Status = STATUS_NOT_FOUND; + while (PathProtocols) + { + /* Attempt to connect the driver for this device epath */ + Status = EfiConnectController(PathArray[--PathProtocols]); + if (NT_SUCCESS(Status)) + { + /* Now enumerate any block I/O devices the driver added */ + Status = EfiLocateHandleBuffer(ByProtocol, + &EfiBlockIoProtocol, + &BlockProtocols, + &BlockArray); + if (!NT_SUCCESS(Status)) + { + break; + } + + /* Loop through each one */ + while (BlockProtocols) + { + /* Check if one of the new devices is the one we want */ + Status = BlockIoEfiCompareDevice(Device, + BlockArray[--BlockProtocols]); + if (NT_SUCCESS(Status)) + { + /* Yep, all done */ + goto Quickie; + } + } + + /* Move on to the next device path */ + BlMmFreeHeap(BlockArray); + BlockArray = NULL; + } + } + } + +Quickie: + /* We're done -- free the array of device path protocols, if any */ + if (PathArray) + { + BlMmFreeHeap(PathArray); + } + + /* We're done -- free the array of block I/O protocols, if any */ + if (BlockArray) + { + BlMmFreeHeap(BlockArray); + } + + /* Return if we found the device or not */ + return Status; +} /*++ * @name EfiGetEfiStatusCode Modified: trunk/reactos/boot/environ/lib/io/device.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/io/device.c?rev=70618&r1=70617&r2=70618&view=diff ============================================================================== --- trunk/reactos/boot/environ/lib/io/device.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/io/device.c [iso-8859-1] Tue Jan 19 18:21:54 2016 @@ -371,7 +371,7 @@ ) { PBL_BLOCK_DEVICE BlockDevice; - PVOID ReadBuffer; // edi@1 + PVOID ReadBuffer; ULONGLONG OffsetEnd, AlignedOffsetEnd, Offset; NTSTATUS Status; @@ -532,24 +532,32 @@ PBL_BLOCK_DEVICE BlockDevice; NTSTATUS Status; + /* Get the device-specific data, which is our block device descriptor */ BlockDevice = DeviceEntry->DeviceSpecificData; + /* Make sure that the buffer and size is valid */ Status = BlockIopBlockInformationCheck(BlockDevice, &Size, BytesRead, &Size); if (NT_SUCCESS(Status)) { - if (BlockDevice->DeviceFlags & 4) - { + /* Check if this is a virtual device or a physical device */ + if (BlockDevice->DeviceFlags & BL_BLOCK_DEVICE_VIRTUAL_FLAG) + { + /* Do a virtual read or write */ Status = BlockIopReadWriteVirtualDevice(DeviceEntry, Buffer, Size, 0, BytesRead); } else { + /* Do a physical read or write */ Status = BlockIopReadPhysicalDevice(DeviceEntry, Buffer, Size, BytesRead); } } else if (BytesRead) { + /* We failed, if the caller wanted bytes read, return 0 */ *BytesRead = 0; } + + /* Return back to the caller */ return Status; } @@ -564,16 +572,25 @@ BlockDevice = DeviceEntry->DeviceSpecificData; - Offset = DeviceInformation->BlockDeviceInfo.Block * BlockDevice->BlockSize + DeviceInformation->BlockDeviceInfo.Offset; + /* Take the current block number and block-offset and conver to full offset */ + Offset = DeviceInformation->BlockDeviceInfo.Block * BlockDevice->BlockSize + + DeviceInformation->BlockDeviceInfo.Offset; + + /* Make sure that the full offset is still within the bounds of the device */ if (Offset > ((BlockDevice->LastBlock + 1) * BlockDevice->BlockSize - 1)) { - EfiPrintf(L"Invalid offset\r\n"); + EfiPrintf(L"Offset out of bounds\r\n"); return STATUS_INVALID_PARAMETER; } + /* Convery the full raw offset into a block number and block-offset */ BlockDevice->Block = Offset / BlockDevice->BlockSize; BlockDevice->Offset = Offset % BlockDevice->BlockSize; + + /* Return the unknown */ BlockDevice->Unknown = DeviceInformation->BlockDeviceInfo.Unknown; + + /* All done */ return STATUS_SUCCESS; } @@ -583,13 +600,12 @@ _Out_ PBL_DEVICE_INFORMATION DeviceInformation ) { - PBL_BLOCK_DEVICE BlockDevice; - - BlockDevice = DeviceEntry->DeviceSpecificData; - + /* Copy the device speciifc data into the block device information */ RtlCopyMemory(&DeviceInformation->BlockDeviceInfo, - BlockDevice, - sizeof(DeviceInformation->BlockDeviceInfo)); + DeviceEntry->DeviceSpecificData, + sizeof(DeviceInformation->BlockDeviceInfo)); + + /* Hardcode the device type */ DeviceInformation->DeviceType = DiskDevice; return STATUS_SUCCESS; } @@ -732,22 +748,28 @@ ) { NTSTATUS Status; - BL_DEVICE_INFORMATION DeviceInformation; - - Status = BlDeviceGetInformation(DeviceId, &DeviceInformation); + BL_DEVICE_INFORMATION DeviceInfo; + + /* Get the current block and offset */ + Status = BlDeviceGetInformation(DeviceId, &DeviceInfo); if (!NT_SUCCESS(Status)) { return Status; } - DeviceInformation.BlockDeviceInfo.Block = Offset / DeviceInformation.BlockDeviceInfo.BlockSize; - DeviceInformation.BlockDeviceInfo.Offset = Offset % DeviceInformation.BlockDeviceInfo.BlockSize; - Status = BlDeviceSetInformation(DeviceId, &DeviceInformation); + /* Get the block and block-offset based on the new raw offset */ + DeviceInfo.BlockDeviceInfo.Block = Offset / DeviceInfo.BlockDeviceInfo.BlockSize; + DeviceInfo.BlockDeviceInfo.Offset = Offset % DeviceInfo.BlockDeviceInfo.BlockSize; + + /* Update the block and offset */ + Status = BlDeviceSetInformation(DeviceId, &DeviceInfo); if (NT_SUCCESS(Status)) { + /* Now issue a read, with this block and offset configured */ Status = BlDeviceRead(DeviceId, Buffer, Size, BytesRead); } + /* All good, return the caller */ return Status; } @@ -828,7 +850,7 @@ } if (Media->MediaPresent) { - BlockDevice->DeviceFlags |= 2; + BlockDevice->DeviceFlags |= BL_BLOCK_DEVICE_PRESENT_FLAG; } /* No clue */ @@ -1212,6 +1234,158 @@ } NTSTATUS +BlockIoEfiCompareDevice ( + _In_ PBL_DEVICE_DESCRIPTOR Device, + _In_ EFI_HANDLE Handle + ) +{ + PBL_LOCAL_DEVICE LocalDeviceInfo, EfiLocalDeviceInfo; + PBL_DEVICE_ENTRY DeviceEntry; + PBL_DEVICE_DESCRIPTOR EfiDevice; + NTSTATUS Status; + + DeviceEntry = NULL; + + /* Check if no device was given */ + if (!Device) + { + /* Fail the comparison */ + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* Check if this is a local disk device */ + if (Device->DeviceType != DiskDevice) + { + /* Nope -- is it a partition device? */ + if ((Device->DeviceType != LegacyPartitionDevice) && + (Device->DeviceType != PartitionDevice)) + { + /* Nope, so we can't compare */ + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* If so, return the device information for the parent disk */ + LocalDeviceInfo = &Device->Partition.Disk; + } + else + { + /* Just return the disk information itself */ + LocalDeviceInfo = &Device->Local; + } + + /* Create an EFI device entry for the EFI device handle */ + Status = BlockIoEfiCreateDeviceEntry(&DeviceEntry, Handle); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Read the descriptor and assume failure for now */ + EfiDevice = DeviceEntry->DeviceDescriptor; + Status = STATUS_UNSUCCESSFUL; + + /* Check if the EFI device is a disk */ + if (EfiDevice->DeviceType != DiskDevice) + { + /* Nope, is it a partition? */ + if ((EfiDevice->DeviceType != LegacyPartitionDevice) && + (EfiDevice->DeviceType != PartitionDevice)) + { + /* Neither, invalid handle so bail out */ + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* Yes, so get the information of the parent disk */ + EfiLocalDeviceInfo = &EfiDevice->Partition.Disk; + } + else + { + /* It's a disk, so get the disk information itself */ + EfiLocalDeviceInfo = &EfiDevice->Local; + } + + /* Are the two devices the same type? */ + if (EfiLocalDeviceInfo->Type != LocalDeviceInfo->Type) + { + /* Nope, that was easy */ + goto Quickie; + } + + /* Yes, what kind of device is the EFI side? */ + switch (EfiLocalDeviceInfo->Type) + { + case LocalDevice: + + /* Local hard drive, compare the signature */ + if (RtlCompareMemory(&EfiLocalDeviceInfo->HardDisk, + &LocalDeviceInfo->HardDisk, + sizeof(LocalDeviceInfo->HardDisk)) == + sizeof(LocalDeviceInfo->HardDisk)) + { + Status = STATUS_SUCCESS; + } + break; + + case FloppyDevice: + case CdRomDevice: + + /* Removable floppy or CD, compare the disk number */ + if (RtlCompareMemory(&EfiLocalDeviceInfo->FloppyDisk, + &LocalDeviceInfo->FloppyDisk, + sizeof(LocalDeviceInfo->FloppyDisk)) == + sizeof(LocalDeviceInfo->FloppyDisk)) + { + Status = STATUS_SUCCESS; + } + break; + + case RamDiskDevice: + + /* RAM disk, compare the size and base information */ + if (RtlCompareMemory(&EfiLocalDeviceInfo->RamDisk, + &LocalDeviceInfo->RamDisk, + sizeof(LocalDeviceInfo->RamDisk)) == + sizeof(LocalDeviceInfo->RamDisk)) + { + Status = STATUS_SUCCESS; + } + break; + + case FileDevice: + + /* File, compare the file identifier */ + if (RtlCompareMemory(&EfiLocalDeviceInfo->File, + &LocalDeviceInfo->File, + sizeof(LocalDeviceInfo->File)) == + sizeof(LocalDeviceInfo->File)) + { + Status = STATUS_SUCCESS; + } + break; + + /* Something else we don't support */ + default: + break; + } + +Quickie: + /* All done, did we have an EFI device entry? */ + if (DeviceEntry) + { + /* Free it, since we only needed it locally for comparison */ + BlMmFreeHeap(DeviceEntry->DeviceDescriptor); + BlockIopFreeAllocations(DeviceEntry->DeviceSpecificData); + BlMmFreeHeap(DeviceEntry); + } + + /* Return back to the caller */ + return Status; +} + +NTSTATUS BlockIoFirmwareOpen ( _In_ PBL_DEVICE_DESCRIPTOR Device, _In_ PBL_BLOCK_DEVICE BlockIoDevice Modified: trunk/reactos/boot/environ/lib/misc/bcdopt.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/bcdopt.c?rev=70618&r1=70617&r2=70618&view=diff ============================================================================== --- trunk/reactos/boot/environ/lib/misc/bcdopt.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/misc/bcdopt.c [iso-8859-1] Tue Jan 19 18:21:54 2016 @@ -622,6 +622,69 @@ } NTSTATUS +BlAppendBootOptionBoolean ( + _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, + _In_ ULONG OptionId + ) +{ + NTSTATUS Status; + PBL_BCD_OPTION Option; + + /* Allocate space for the entry -- remember BOOLEANs are USHORTs in BCD */ + Option = BlMmAllocateHeap(sizeof(*Option) + sizeof(USHORT)); + if (!Option) + { + return STATUS_NO_MEMORY; + } + + /* Initialize it and set the boolean to TRUE */ + RtlZeroMemory(Option, sizeof(*Option) + sizeof(USHORT)); + Option->DataSize = sizeof(USHORT); + Option->Type = OptionId; + Option->DataOffset = sizeof(*Option); + *(PBOOLEAN)(Option + 1) = TRUE; + + /* Append it */ + Status = BlAppendBootOptions(AppEntry, Option); + + /* We're all done, free our initial option */ + BlMmFreeHeap(Option); + return Status; +} + +NTSTATUS +BlAppendBootOptionInteger ( + _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, + _In_ ULONG OptionId, + _In_ ULONGLONG Value + ) +{ + NTSTATUS Status; + PBL_BCD_OPTION Option; + + /* Allocate space for the entry */ + Option = BlMmAllocateHeap(sizeof(*Option) + sizeof(Value)); + if (!Option) + { + return STATUS_NO_MEMORY; + } + + /* Initialize it and set the integer to the given value */ + RtlZeroMemory(Option, sizeof(*Option) + sizeof(Value)); + Option->DataSize = sizeof(Value); + Option->Type = OptionId; + Option->DataOffset = sizeof(*Option); + *(PULONGLONG)(Option + 1) = Value; + + /* Append it */ + Status = BlAppendBootOptions(AppEntry, Option); + + /* We're all done, free our initial option */ + BlMmFreeHeap(Option); + return Status; +} + +NTSTATUS BlAppendBootOptionString ( _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, _In_ PWCHAR OptionString