[BOOTLIB]: Implement MmArchTranslateVirtualAddress for non-paging mode. Stub Mmx86Tra...
[reactos.git] / reactos / boot / environ / lib / firmware / efi / firmware.c
index 97c592f..48cdffb 100644 (file)
@@ -33,9 +33,14 @@ EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
 EFI_GUID EfiBlockIoProtocol = EFI_BLOCK_IO_PROTOCOL_GUID;
 EFI_GUID EfiRootAcpiTableGuid = EFI_ACPI_20_TABLE_GUID;
 EFI_GUID EfiRootAcpiTable10Guid = EFI_ACPI_TABLE_GUID;
+EFI_GUID EfiGlobalVariable = EFI_GLOBAL_VARIABLE;
+EFI_GUID BlpEfiSecureBootPrivateNamespace = { 0x77FA9ABD , 0x0359, 0x4D32, { 0xBD, 0x60, 0x28, 0xF4, 0xE7, 0x8F, 0x78, 0x4B } };
 
 WCHAR BlScratchBuffer[8192];
 
+BOOLEAN BlpFirmwareChecked;
+BOOLEAN BlpFirmwareEnabled;
+
 /* FUNCTIONS *****************************************************************/
 
 EFI_DEVICE_PATH *
@@ -113,7 +118,7 @@ EfiGetLeafNode (
         }
     }
 
-    /* This now contains the deepeest (leaf) node */
+    /* This now contains the deepest (leaf) node */
     return DevicePath;
 }
 
@@ -138,7 +143,17 @@ EfiPrintf (
     }
     else
     {
-        /* FIXME: @TODO: Not yet supported */
+        /* Switch to real mode */
+        BlpArchSwitchContext(BlRealMode);
+
+        /* Call EFI directly */
+        if (EfiConOut != NULL)
+        {
+            EfiConOut->OutputString(EfiConOut, BlScratchBuffer);
+        }
+
+        /* Switch back to protected mode */
+        BlpArchSwitchContext(BlProtectedMode);
     }
 
     /* All done */
@@ -268,6 +283,159 @@ EfiCloseProtocol (
     return Status;
 }
 
+NTSTATUS
+EfiGetVariable (
+    _In_ PWCHAR VariableName,
+    _In_ EFI_GUID* VendorGuid,
+    _Out_opt_ PULONG Attributes,
+    _Inout_ PULONG DataSize,
+    _Out_ PVOID Data
+    )
+{
+    EFI_STATUS EfiStatus;
+    NTSTATUS Status;
+    BL_ARCH_MODE OldMode;
+    ULONG LocalAttributes;
+
+    /* Are we in protected mode? */
+    OldMode = CurrentExecutionContext->Mode;
+    if (OldMode != BlRealMode)
+    {
+        /* FIXME: Not yet implemented */
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    /* Call the runtime API */
+    EfiStatus = EfiRT->GetVariable(VariableName,
+                                   VendorGuid,
+                                   (UINT32*)&LocalAttributes,
+                                   (UINTN*)DataSize,
+                                   Data);
+
+    /* Switch back to protected mode if we came from there */
+    if (OldMode != BlRealMode)
+    {
+        BlpArchSwitchContext(OldMode);
+    }
+
+    /* Return attributes back to the caller if asked to */
+    if (Attributes)
+    {
+        *Attributes = LocalAttributes;
+    }
+
+    /* Convert the error to an NTSTATUS and return it */
+    Status = EfiGetNtStatusCode(EfiStatus);
+    return Status;
+}
+
+NTSTATUS
+BlpSecureBootEFIIsEnabled (
+    VOID
+    )
+{
+    NTSTATUS Status;
+    BOOLEAN SetupMode, SecureBoot;
+    ULONG DataSize;
+
+    /* Assume setup mode enabled, and no secure boot */
+    SecureBoot = FALSE;
+    SetupMode = TRUE;
+
+    /* Get the SetupMode variable */
+    DataSize = sizeof(SetupMode);
+    Status = EfiGetVariable(L"SetupMode",
+                            &EfiGlobalVariable,
+                            NULL,
+                            &DataSize,
+                            &SetupMode);
+    if (NT_SUCCESS(Status))
+    {
+        /* If it worked, get the SecureBoot variable */
+        DataSize = sizeof(SecureBoot);
+        Status = EfiGetVariable(L"SecureBoot",
+                                &EfiGlobalVariable,
+                                NULL,
+                                &DataSize,
+                                &SecureBoot);
+        if (NT_SUCCESS(Status))
+        {
+            /* In setup mode or without secureboot turned on, return failure */
+            if ((SecureBoot != TRUE) || (SetupMode))
+            {
+                Status = STATUS_INVALID_SIGNATURE;
+            }
+
+            // BlpSbdiStateFlags |= 8u;
+        }
+    }
+
+    /* Return secureboot status */
+    return Status;
+}
+
+NTSTATUS
+BlSecureBootIsEnabled (
+    _Out_ PBOOLEAN SecureBootEnabled
+    )
+{
+    NTSTATUS Status;
+
+    /* Have we checked before ? */
+    if (!BlpFirmwareChecked)
+    {
+        /* First time checking */
+        Status = BlpSecureBootEFIIsEnabled();
+        if NT_SUCCESS(Status)
+        {
+            /* Yep, it's on */
+            BlpFirmwareEnabled = TRUE;
+        }
+
+        /* Don't check again */
+        BlpFirmwareChecked = TRUE;
+    }
+
+    /* Return the firmware result */
+    *SecureBootEnabled = BlpFirmwareEnabled;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+BlSecureBootCheckForFactoryReset (
+    VOID
+    )
+{
+    BOOLEAN SecureBootEnabled;
+    NTSTATUS Status;
+    ULONG DataSize;
+
+    /* Initialize locals */
+    DataSize = 0;
+    SecureBootEnabled = FALSE;
+
+    /* Check if secureboot is enabled */
+    Status = BlSecureBootIsEnabled(&SecureBootEnabled);
+    if (!(NT_SUCCESS(Status)) || !(SecureBootEnabled))
+    {
+        /* It's not. Check if there's a revocation list */
+        Status = EfiGetVariable(L"RevocationList",
+                                &BlpEfiSecureBootPrivateNamespace,
+                                NULL,
+                                &DataSize,
+                                NULL);
+        if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL))
+        {
+            /* We don't support this yet */
+            EfiPrintf(L"Not yet supported\r\n");
+            Status = STATUS_NOT_IMPLEMENTED;
+        }
+    }
+
+    /* Return back to the caller */
+    return Status;
+}
+
 NTSTATUS
 EfiConInReset (
     VOID
@@ -396,13 +564,27 @@ EfiGetMemoryMap (
 {
     BL_ARCH_MODE OldMode;
     EFI_STATUS EfiStatus;
+    PHYSICAL_ADDRESS MemoryMapSizePhysical, MemoryMapPhysical, MapKeyPhysical;
+    PHYSICAL_ADDRESS DescriptorSizePhysical, DescriptorVersionPhysical;
 
     /* Are we in protected mode? */
     OldMode = CurrentExecutionContext->Mode;
     if (OldMode != BlRealMode)
     {
-        /* FIXME: Not yet implemented */
-        return STATUS_NOT_IMPLEMENTED;
+        /* Convert all of the addresses to physical */
+        BlMmTranslateVirtualAddress(MemoryMapSize, &MemoryMapSizePhysical);
+        MemoryMapSize = (UINTN*)MemoryMapSizePhysical.LowPart;
+        BlMmTranslateVirtualAddress(MemoryMap, &MemoryMapPhysical);
+        MemoryMap = (EFI_MEMORY_DESCRIPTOR*)MemoryMapPhysical.LowPart;
+        BlMmTranslateVirtualAddress(MapKey, &MapKeyPhysical);
+        MapKey = (UINTN*)MapKeyPhysical.LowPart;
+        BlMmTranslateVirtualAddress(DescriptorSize, &DescriptorSizePhysical);
+        DescriptorSize = (UINTN*)DescriptorSizePhysical.LowPart;
+        BlMmTranslateVirtualAddress(DescriptorVersion, &DescriptorVersionPhysical);
+        DescriptorVersion = (UINTN*)DescriptorVersionPhysical.LowPart;
+
+        /* Switch to real mode */
+        BlpArchSwitchContext(BlProtectedMode);
     }
 
     /* Make the EFI call */
@@ -791,7 +973,7 @@ EfiGopSetMode (
     if ((ModeChanged) && (NT_SUCCESS(Status)))
     {
         /* FIXME @TODO: Should be BlStatusPrint */
-        EfiPrintf(L"Console video mode  set to 0x%x\r\r\n", Mode);
+        EfiPrintf(L"Console video mode set to 0x%x\r\n", Mode);
     }
 
     /* Convert the error to an NTSTATUS */
@@ -891,6 +1073,42 @@ EfiResetSystem (
     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
 EfiAllocatePages (
     _In_ ULONG Type,
@@ -1171,7 +1389,7 @@ MmFwGetMemoryMap (
     NTSTATUS Status;
     ULONGLONG Pages, StartPage, EndPage;
     UINTN EfiMemoryMapSize, MapKey, DescriptorSize, DescriptorVersion;
-    EFI_PHYSICAL_ADDRESS EfiBuffer;
+    EFI_PHYSICAL_ADDRESS EfiBuffer = 0;
     EFI_MEMORY_DESCRIPTOR* EfiMemoryMap;
     EFI_STATUS EfiStatus;
     BL_ARCH_MODE OldMode;
@@ -1327,7 +1545,7 @@ MmFwGetMemoryMap (
 
     /* Loop the EFI memory map */
 #if 0
-    EfiPrintf(L"UEFI MEMORY MAP\n\r\n");
+    EfiPrintf(L"UEFI MEMORY MAP\r\n\r\n");
     EfiPrintf(L"TYPE        START              END                   ATTRIBUTES\r\n");
     EfiPrintf(L"===============================================================\r\n");
 #endif
@@ -1486,8 +1704,8 @@ MmFwGetMemoryMap (
         Status = MmMdAddDescriptorToList(MemoryMap,
                                          Descriptor,
                                          BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG |
-                                         (Flags & BL_MM_FLAG_REQUEST_COALESCING) ?
-                                         BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG : 0);
+                                         ((Flags & BL_MM_FLAG_REQUEST_COALESCING) ?
+                                          BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG : 0));
         if (!NT_SUCCESS(Status))
         {
             EfiPrintf(L"Failed to add full descriptor: %lx\r\n", Status);
@@ -1530,7 +1748,7 @@ BlpFwInitialize (
     NTSTATUS Status = STATUS_SUCCESS;
     EFI_KEY_TOGGLE_STATE KeyToggleState;
 
-    /* Check if we have vaild firmware data */
+    /* Check if we have valid firmware data */
     if (!(FirmwareData) || !(FirmwareData->Version))
     {
         return STATUS_INVALID_PARAMETER;
@@ -1564,7 +1782,7 @@ BlpFwInitialize (
             /* FIXME: Not supported */
             Status = STATUS_NOT_SUPPORTED;
         }
-        else if (FirmwareData->Version >= 2)
+        else if (FirmwareData->Version >= BL_FIRMWARE_DESCRIPTOR_VERSION)
         {
             /* Version 2 -- save the data */
             EfiFirmwareData = *FirmwareData;
@@ -1590,6 +1808,107 @@ BlpFwInitialize (
     return Status;
 }
 
+NTSTATUS
+BlFwGetParameters (
+    _In_ PBL_FIRMWARE_DESCRIPTOR Parameters
+    )
+{
+    /* Make sure we got an argument */
+    if (!Parameters)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Copy the static data */
+    *Parameters = *EfiFirmwareParameters;
+    return STATUS_SUCCESS;
+}
+
+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