GUID BmApplicationIdentifier;
PWCHAR BootDirectory;
+BL_BOOT_ERROR BmpErrorBuffer;
+PBL_BOOT_ERROR BmpInternalBootError;
+BL_PACKED_BOOT_ERROR BmpPackedBootError;
+
+BOOLEAN BmBootIniUsed;
+WCHAR BmpFileNameBuffer[128];
+PWCHAR ParentFileName = L"";
+
/* FUNCTIONS *****************************************************************/
NTSTATUS
/* All done! */
return Status;
-
}
+
NTSTATUS
BmFwInitializeBootDirectoryPath (
VOID
goto Quickie;
}
+ /* Save the boot directory */
BootDirectory = L"\\EFI\\Microsoft\\Boot";
Quickie:
return Status;
}
+NTSTATUS
+BmOpenBootIni (
+ VOID
+ )
+{
+ /* Don't yet handled boot.ini */
+ return STATUS_NOT_FOUND;
+}
+
+ULONG
+BmpFatalErrorMessageFilter (
+ _In_ NTSTATUS ErrorStatus,
+ _Out_ PULONG ErrorResourceId
+ )
+{
+ ULONG Result;
+
+ /* Assume no message for now, check for known status message */
+ Result = 0;
+ switch (ErrorStatus)
+ {
+ /* Convert each status to a resource ID */
+ case STATUS_UNEXPECTED_IO_ERROR:
+ *ErrorResourceId = 9017;
+ Result = 1;
+ break;
+ case STATUS_IMAGE_CHECKSUM_MISMATCH:
+ *ErrorResourceId = 9018;
+ break;
+ case STATUS_INVALID_IMAGE_WIN_64:
+ *ErrorResourceId = 9016;
+ break;
+ case 0xC0000428:
+ *ErrorResourceId = 9019;
+ Result = 2;
+ break;
+ case 0xC0210000:
+ *ErrorResourceId = 9013;
+ break;
+ }
+
+ /* Return the type of message */
+ return Result;
+}
+
+VOID
+BmErrorPurge (
+ VOID
+ )
+{
+ /* Check if a boot error is present */
+ if (BmpPackedBootError.BootError)
+ {
+ /* Purge it */
+ BlMmFreeHeap(BmpPackedBootError.BootError);
+ BmpPackedBootError.BootError = NULL;
+ }
+
+ /* Zero out the packed buffer */
+ BmpPackedBootError.Size = 0;
+ BmpInternalBootError = NULL;
+ RtlZeroMemory(&BmpErrorBuffer, sizeof(BmpErrorBuffer));
+}
+
+VOID
+BmpErrorLog (
+ _In_ ULONG ErrorCode,
+ _In_ NTSTATUS ErrorStatus,
+ _In_ ULONG ErrorMsgId,
+ _In_ PWCHAR FileName,
+ _In_ ULONG HelpMsgId
+ )
+{
+ PWCHAR ErrorMsgString;
+
+ /* Check if we already had an error */
+ if (BmpInternalBootError)
+ {
+ /* Purge it */
+ BmErrorPurge();
+ }
+
+ /* Find the string for this error ID */
+ ErrorMsgString = BlResourceFindMessage(ErrorMsgId);
+ if (ErrorMsgString)
+ {
+ /* Fill out the error buffer */
+ BmpErrorBuffer.Unknown1 = 0;
+ BmpErrorBuffer.Unknown2 = 0;
+ BmpErrorBuffer.ErrorString = ErrorMsgString;
+ BmpErrorBuffer.FileName = FileName;
+ BmpErrorBuffer.ErrorCode = ErrorCode;
+ BmpErrorBuffer.ErrorStatus = ErrorStatus;
+ BmpErrorBuffer.HelpMsgId = HelpMsgId;
+ BmpInternalBootError = &BmpErrorBuffer;
+ }
+}
+
+VOID
+BmFatalErrorEx (
+ _In_ ULONG ErrorCode,
+ _In_ ULONG_PTR Parameter1,
+ _In_ ULONG_PTR Parameter2,
+ _In_ ULONG_PTR Parameter3,
+ _In_ ULONG_PTR Parameter4
+ )
+{
+ PWCHAR FileName, Buffer;
+ NTSTATUS ErrorStatus;
+ WCHAR FormatString[256];
+ ULONG ErrorResourceId, ErrorHelpId;
+ BOOLEAN Restart, NoError;
+
+ /* Assume no buffer for now */
+ Buffer = NULL;
+
+ /* Check what error code is being raised */
+ switch (ErrorCode)
+ {
+ /* Error reading the BCD */
+ case BL_FATAL_ERROR_BCD_READ:
+
+ /* Check if we have a name for the BCD file */
+ if (Parameter1)
+ {
+ /* Check if the name fits into our buffer */
+ FileName = (PWCHAR)Parameter1;
+ if (wcslen(FileName) < sizeof(BmpFileNameBuffer))
+ {
+ /* Copy it in there */
+ Buffer = BmpFileNameBuffer;
+ wcsncpy(BmpFileNameBuffer,
+ FileName,
+ RTL_NUMBER_OF(BmpFileNameBuffer));
+ }
+ }
+
+ /* If we don't have a buffer, use an empty one */
+ if (!Buffer)
+ {
+ Buffer = ParentFileName;
+ }
+
+ /* The NTSTATUS code is in parameter 2*/
+ ErrorStatus = (NTSTATUS)Parameter2;
+
+ /* Build the error string */
+ swprintf(FormatString,
+ L"\nAn error occurred (%08x) while attempting"
+ L"to read the boot configuration data file %s\n",
+ ErrorStatus,
+ Buffer);
+
+ /* Select the resource ID message */
+ ErrorResourceId = 9002;
+ break;
+
+ default:
+
+ /* The rest is not yet handled */
+ EfiPrintf(L"Unexpected fatal error: %lx\n", ErrorCode);
+ while (1);
+ break;
+ }
+
+ /* Check if the BCD option for restart is set */
+ BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
+ BcdLibraryBoolean_RestartOnFailure,
+ &Restart);
+ if (Restart)
+ {
+ /* Yes, so no error should be shown since we'll auto-restart */
+ NoError = TRUE;
+ }
+ else
+ {
+ /* Check if the option for not showing errors is set in the BCD */
+ BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
+ BcdBootMgrBoolean_NoErrorDisplay,
+ &NoError);
+ }
+
+ /* Do we want an error? */
+ if (!NoError)
+ {
+ /* Yep, print it and then raise an error */
+ BlStatusPrint(FormatString);
+ BlStatusError(1, ErrorCode, Parameter1, Parameter2, Parameter3);
+ }
+
+ /* Get the help message ID */
+ ErrorHelpId = BmpFatalErrorMessageFilter(ErrorStatus, &ErrorResourceId);
+ BmpErrorLog(ErrorCode, ErrorStatus, ErrorResourceId, Buffer, ErrorHelpId);
+}
+
+NTSTATUS
+BmpFwGetFullPath (
+ _In_ PWCHAR FileName,
+ _Out_ PWCHAR* FullPath
+ )
+{
+ NTSTATUS Status;
+ ULONG BootDirLength, BootDirLengthWithNul;
+ ULONG PathLength, FullPathLength;
+
+ /* Compute the length of the directory, and add a NUL */
+ BootDirLength = wcslen(BootDirectory);
+ BootDirLengthWithNul = BootDirLength + 1;
+ if (BootDirLengthWithNul < BootDirLength)
+ {
+ /* This would overflow */
+ BootDirLengthWithNul = -1;
+ Status = STATUS_INTEGER_OVERFLOW;
+ }
+ else
+ {
+ /* We have space */
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Fail on overflow */
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ /* Add the length of the file, make sure it fits */
+ PathLength = wcslen(FileName);
+ FullPathLength = PathLength + BootDirLength;
+ if (FullPathLength < PathLength)
+ {
+ /* Nope */
+ FullPathLength = -1;
+ Status = STATUS_INTEGER_OVERFLOW;
+ }
+ else
+ {
+ /* All good */
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Fail on overflow */
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ /* Allocate the full path */
+ FullPathLength = FullPathLength * sizeof(WCHAR);
+ *FullPath = BlMmAllocateHeap(FullPathLength);
+ if (*FullPath)
+ {
+ /* Copy the directory followed by the file name */
+ wcsncpy(*FullPath, BootDirectory, FullPathLength / sizeof(WCHAR));
+ wcsncat(*FullPath, FileName, FullPathLength / sizeof(WCHAR));
+ }
+ else
+ {
+ /* Bail out since we have no memory */
+ Status = STATUS_NO_MEMORY;
+ }
+
+Quickie:
+ /* Return to caller */
+ return Status;
+}
+
+NTSTATUS
+BmOpenDataStore (
+ _Out_ PHANDLE Handle
+ )
+{
+ NTSTATUS Status;
+ PBL_DEVICE_DESCRIPTOR BcdDevice;
+ PWCHAR BcdPath, FullPath, PathBuffer;
+ BOOLEAN HavePath;
+ ULONG PathLength, PathLengthWithNul, FullSize;
+ PVOID FinalBuffer;
+ UNICODE_STRING BcdString;
+
+ /* Initialize variables */
+ PathBuffer = NULL;
+ BcdDevice = NULL;
+ BcdPath = NULL;
+ HavePath = FALSE;
+
+ /* Check if a boot.ini file exists */
+ Status = BmOpenBootIni();
+ if (NT_SUCCESS(Status))
+ {
+ BmBootIniUsed = TRUE;
+ }
+
+ /* Check on which device the BCD is */
+ Status = BlGetBootOptionDevice(BlpApplicationEntry.BcdData,
+ BcdBootMgrDevice_BcdDevice,
+ &BcdDevice,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* It's not on a custom device, so it must be where we are */
+ Status = BlGetBootOptionDevice(BlpApplicationEntry.BcdData,
+ BcdLibraryDevice_ApplicationDevice,
+ &BcdDevice,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* This BCD option is required */
+ goto Quickie;
+ }
+ }
+
+ /* Next, check what file contains the BCD */
+ Status = BlGetBootOptionString(BlpApplicationEntry.BcdData,
+ BcdBootMgrString_BcdFilePath,
+ &BcdPath);
+ if (NT_SUCCESS(Status))
+ {
+ /* We don't handle custom BCDs yet */
+ EfiPrintf(L"Not handled\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ goto Quickie;
+ }
+
+ /* Now check if the BCD is on a remote share */
+ if (BcdDevice->DeviceType == UdpDevice)
+ {
+ /* Nope. Nope. Nope */
+ EfiPrintf(L"Not handled\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ goto Quickie;
+ }
+
+ /* Otherwise, compute the hardcoded path of the BCD */
+ Status = BmpFwGetFullPath(L"\\BCD", &FullPath);
+ EfiPrintf(L"Status: %lx %s\r\n", Status, FullPath);
+ if (!NT_SUCCESS(Status))
+ {
+ /* User the raw path */
+ PathBuffer = BcdPath;
+ }
+ else
+ {
+ /* Use the path we got */
+ PathBuffer = FullPath;
+ HavePath = TRUE;
+ }
+
+ /* Check if we failed to get the BCD path */
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ /* Add a NUL to the path, make sure it'll fit */
+ Status = STATUS_SUCCESS;
+ PathLength = wcslen(PathBuffer);
+ PathLengthWithNul = PathLength + 1;
+ if (PathLengthWithNul < PathLength)
+ {
+ PathLengthWithNul = -1;
+ Status = STATUS_INTEGER_OVERFLOW;
+ }
+
+ /* Bail out if it doesn't fit */
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ /* Now add the size of the path to the device path, check if it fits */
+ PathLengthWithNul = PathLengthWithNul * sizeof(WCHAR);
+ FullSize = PathLengthWithNul + BcdDevice->Size;
+ if (FullSize < BcdDevice->Size)
+ {
+ FullSize = -1;
+ Status = STATUS_INTEGER_OVERFLOW;
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ /* Bail out if it doesn't fit */
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ /* Allocate a final structure to hold both entities */
+ FinalBuffer = BlMmAllocateHeap(FullSize);
+ if (!FinalBuffer)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Quickie;
+ }
+
+ /* Copy the device path and file path into the final buffer */
+ RtlCopyMemory(FinalBuffer, BcdDevice, BcdDevice->Size);
+ RtlCopyMemory((PVOID)((ULONG_PTR)FinalBuffer + BcdDevice->Size),
+ PathBuffer,
+ PathLengthWithNul);
+
+ /* Now tell the BCD engine to open the store */
+ BcdString.Length = FullSize;
+ BcdString.MaximumLength = FullSize;
+ BcdString.Buffer = FinalBuffer;
+ Status = BcdOpenStoreFromFile(&BcdString, Handle);
+
+ /* Free our final buffer */
+ BlMmFreeHeap(FinalBuffer);
+
+Quickie:
+ /* Did we allocate a device? */
+ if (BcdDevice)
+ {
+ /* Free it */
+ BlMmFreeHeap(BcdDevice);
+ }
+
+ /* Is this the failure path? */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Raise a fatal error */
+ BmFatalErrorEx(1, (ULONG_PTR)PathBuffer, Status, 0, 0);
+ }
+
+ /* Did we get an allocated path? */
+ if ((PathBuffer) && (HavePath))
+ {
+ /* Free it */
+ BlMmFreeHeap(PathBuffer);
+ }
+
+ /* Return back to the caller */
+ return Status;
+}
/*++
* @name BmMain
PBL_RETURN_ARGUMENTS ReturnArguments;
BOOLEAN RebootOnError;
PGUID AppIdentifier;
-// HANDLE BcdHandle;
+ HANDLE BcdHandle;
EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\n");
/* None was given, so set our default one */
AppIdentifier = (PGUID)&GUID_WINDOWS_BOOTMGR;
}
-
+
/* Save our identifier */
BmApplicationIdentifier = *AppIdentifier;
/* Initialize the file system to open a handle to our root boot directory */
BmFwInitializeBootDirectoryPath();
- //Status = BmOpenDataStore(&BcdHandle);
+ /* Load and initialize the boot configuration database (BCD) */
+ Status = BmOpenDataStore(&BcdHandle);
+ EfiPrintf(L"BCD Open: %lx\r\n", Status);
+ /* do more stuff!! */
EfiPrintf(L"We are A-OK!\r\n");
EfiStall(10000000);