/** Initialize all the stuff needed for on-demand paging hooks for PI<->Framework CpuSaveStates marshalling. @param[in] FrameworkSmst Framework SMM system table pointer. **/ VOID InitHook ( IN EFI_SMM_SYSTEM_TABLE *FrameworkSmst ) { UINTN NumCpuStatePages; UINTN CpuStatePage; UINTN Bottom2MPage; UINTN Top2MPage; mPageTableHookEnabled = FALSE; NumCpuStatePages = EFI_SIZE_TO_PAGES (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE)); // // Only hook page table for X64 image and less than 2MB needed to hold all CPU Save States // if (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64) && NumCpuStatePages <= EFI_SIZE_TO_PAGES (SIZE_2MB)) { // // Allocate double page size to make sure all CPU Save States are in one 2MB page. // CpuStatePage = (UINTN)AllocatePages (NumCpuStatePages * 2); ASSERT (CpuStatePage != 0); Bottom2MPage = CpuStatePage & ~(SIZE_2MB-1); Top2MPage = (CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages * 2) - 1) & ~(SIZE_2MB-1); if (Bottom2MPage == Top2MPage || CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages * 2) - Top2MPage >= EFI_PAGES_TO_SIZE (NumCpuStatePages) ) { // // If the allocated 4KB pages are within the same 2MB page or higher portion is larger, use higher portion pages. // FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)(CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages)); FreePages ((VOID*)CpuStatePage, NumCpuStatePages); } else { FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)CpuStatePage; FreePages ((VOID*)(CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages)), NumCpuStatePages); } // // Add temporary working buffer for hooking // mShadowSaveState = (EFI_SMM_CPU_SAVE_STATE*) AllocatePool (sizeof (EFI_SMM_CPU_SAVE_STATE)); ASSERT (mShadowSaveState != NULL); // // Allocate and initialize 4KB Page Table for hooking CpuSaveState. // Replace the original 2MB PDE with new 4KB page table. // mCpuStatePageTable = InitCpuStatePageTable (FrameworkSmst->CpuSaveState); // // Mark PTE for CpuSaveState as non-exist. // HookCpuStateMemory (FrameworkSmst->CpuSaveState); HookPageFaultHandler (); CpuFlushTlb (); mPageTableHookEnabled = TRUE; } mHookInitialized = TRUE; }
EFI_STATUS XenGetSharedInfoPage ( IN OUT XENBUS_DEVICE *Dev ) { xen_add_to_physmap_t Parameter; ASSERT (Dev->SharedInfo == NULL); Parameter.domid = DOMID_SELF; Parameter.space = XENMAPSPACE_shared_info; Parameter.idx = 0; // // using reserved page because the page is not released when Linux is // starting because of the add_to_physmap. QEMU might try to access the // page, and fail because it have no right to do so (segv). // Dev->SharedInfo = AllocateReservedPages (1); Parameter.gpfn = (UINTN) Dev->SharedInfo >> EFI_PAGE_SHIFT; if (XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameter) != 0) { FreePages (Dev->SharedInfo, 1); Dev->SharedInfo = NULL; return EFI_LOAD_ERROR; } return EFI_SUCCESS; }
EFI_STATUS DestroyMmcHostInstance ( IN MMC_HOST_INSTANCE* MmcHostInstance ) { EFI_STATUS Status; // Uninstall Protocol Interfaces Status = gBS->UninstallMultipleProtocolInterfaces ( MmcHostInstance->MmcHandle, &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo), &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath, NULL ); ASSERT_EFI_ERROR (Status); // Free Memory allocated for the instance if (MmcHostInstance->BlockIo.Media) { FreePool(MmcHostInstance->BlockIo.Media); } if (MmcHostInstance->CardInfo.ECSDData) { FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD))); } FreePool (MmcHostInstance); return Status; }
VOID ShutdownEfi ( VOID ) { EFI_STATUS Status; UINTN MemoryMapSize; EFI_MEMORY_DESCRIPTOR *MemoryMap; UINTN MapKey; UINTN DescriptorSize; UINTN DescriptorVersion; UINTN Pages; MemoryMap = NULL; MemoryMapSize = 0; do { Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); if (Status == EFI_BUFFER_TOO_SMALL) { Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1; MemoryMap = AllocatePages (Pages); // // Get System MemoryMap // Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); // Don't do anything between the GetMemoryMap() and ExitBootServices() if (!EFI_ERROR (Status)) { Status = gBS->ExitBootServices (gImageHandle, MapKey); if (EFI_ERROR (Status)) { FreePages (MemoryMap, Pages); MemoryMap = NULL; MemoryMapSize = 0; } } } } while (EFI_ERROR (Status)); //Clean and invalidate caches. WriteBackInvalidateDataCache(); InvalidateInstructionCache(); //Turning off Caches and MMU ArmDisableDataCache (); ArmDisableInstructionCache (); ArmDisableMmu (); }
/** Frees one or more 4KB pages that were previously allocated with one of the aligned page allocation functions in the Memory Allocation Library. Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer must have been allocated on a previous call to the aligned page allocation services of the Memory Allocation Library. If it is not possible to free allocated pages, then this function will perform no actions. If Buffer was not allocated with an aligned page allocation function in the Memory Allocation Library, then ASSERT(). If Pages is zero, then ASSERT(). @param Buffer The pointer to the buffer of pages to free. @param Pages The number of 4 KB pages to free. **/ VOID EFIAPI FreeAlignedPages ( IN VOID *Buffer, IN UINTN Pages ) { FreePages (Buffer, Pages); }
/** Tear down the internal resources of a configured virtio ring. The caller is responsible to stop the host from using this ring before invoking this function: the VSTAT_DRIVER_OK bit must be clear in VhdrDeviceStatus. @param[out] Ring The virtio ring to clean up. **/ VOID EFIAPI VirtioRingUninit ( IN OUT VRING *Ring ) { FreePages (Ring->Base, Ring->NumPages); SetMem (Ring, sizeof *Ring, 0x00); }
EFI_STATUS ShutdownUefiBootServices ( VOID ) { EFI_STATUS Status; UINTN MemoryMapSize; EFI_MEMORY_DESCRIPTOR *MemoryMap; UINTN MapKey; UINTN DescriptorSize; UINT32 DescriptorVersion; UINTN Pages; MemoryMap = NULL; MemoryMapSize = 0; Pages = 0; do { Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); if (Status == EFI_BUFFER_TOO_SMALL) { Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1; MemoryMap = AllocatePages (Pages); // // Get System MemoryMap // Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); } // Don't do anything between the GetMemoryMap() and ExitBootServices() if (!EFI_ERROR(Status)) { Status = gBS->ExitBootServices (gImageHandle, MapKey); if (EFI_ERROR(Status)) { FreePages (MemoryMap, Pages); MemoryMap = NULL; MemoryMapSize = 0; } } } while (EFI_ERROR(Status)); return Status; }
/** Frees memory that was allocated with DmaAllocateBuffer(). @param Pages The number of pages to free. @param HostAddress The base system memory address of the allocated range. @retval EFI_SUCCESS The requested memory pages were freed. @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages was not allocated with DmaAllocateBuffer(). **/ EFI_STATUS EFIAPI DmaFreeBuffer ( IN UINTN Pages, IN VOID *HostAddress ) { if (HostAddress == NULL) { return EFI_INVALID_PARAMETER; } FreePages (HostAddress, Pages); return EFI_SUCCESS; }
DynamicStack& DynamicStack::operator=(DynamicStack&& other) { if (this != &other) { FreePages(); _pageSize = other._pageSize; _firstPage = other._firstPage; other._pageSize = 0; other._firstPage = nullptr; } return *this; }
/** Frees memory that was allocated with AllocateBuffer(). @param This The protocol instance pointer. @param Pages The number of pages to free. @param HostAddress The base system memory address of the allocated range. @retval EFI_SUCCESS The requested memory pages were freed. @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages was not allocated with AllocateBuffer(). **/ EFI_STATUS EFIAPI IoMmuFreeBuffer ( IN EDKII_IOMMU_PROTOCOL *This, IN UINTN Pages, IN VOID *HostAddress ) { UINTN CommonBufferPages; COMMON_BUFFER_HEADER *CommonBufferHeader; CommonBufferPages = Pages + 1; CommonBufferHeader = (COMMON_BUFFER_HEADER *)( (UINTN)HostAddress - EFI_PAGE_SIZE ); // // Check the signature. // ASSERT (CommonBufferHeader->Signature == COMMON_BUFFER_SIG); if (CommonBufferHeader->Signature != COMMON_BUFFER_SIG) { return EFI_INVALID_PARAMETER; } // // Free the stash buffer. This buffer was always encrypted, so no need to // zero it. // FreePages (CommonBufferHeader->StashBuffer, Pages); DEBUG (( DEBUG_VERBOSE, "%a Address 0x%Lx Pages 0x%Lx\n", __FUNCTION__, (UINT64)(UINTN)HostAddress, (UINT64)Pages )); // // Release the common buffer itself. Unmap() has re-encrypted it in-place, so // no need to zero it. // return gBS->FreePages ((UINTN)CommonBufferHeader, CommonBufferPages); }
STATIC EFI_STATUS EFIAPI EmmcIdentificationMode ( IN MMC_HOST_INSTANCE *MmcHostInstance, IN OCR_RESPONSE Response ) { EFI_MMC_HOST_PROTOCOL *Host; EFI_BLOCK_IO_MEDIA *Media; EFI_STATUS Status; EMMC_DEVICE_STATE State; UINT32 RCA; Host = MmcHostInstance->MmcHost; Media = MmcHostInstance->BlockIo.Media; // Fetch card identity register Status = Host->SendCommand (Host, MMC_CMD2, 0); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to send CMD2, Status=%r.\n", Status)); return Status; } Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CIDData)); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): CID retrieval error, Status=%r.\n", Status)); return Status; } // Assign a relative address value to the card MmcHostInstance->CardInfo.RCA = ++mEmmcRcaCount; // TODO: might need a more sophisticated way of doing this RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET; Status = Host->SendCommand (Host, MMC_CMD3, RCA); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): RCA set error, Status=%r.\n", Status)); return Status; } // Fetch card specific data Status = Host->SendCommand (Host, MMC_CMD9, RCA); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to send CMD9, Status=%r.\n", Status)); return Status; } Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CSDData)); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): CSD retrieval error, Status=%r.\n", Status)); return Status; } // Select the card Status = Host->SendCommand (Host, MMC_CMD7, RCA); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status)); } if (MMC_HOST_HAS_SETIOS(Host)) { // Set 1-bit bus width Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status)); return Status; } // Set 1-bit bus width for EXTCSD Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status)); return Status; } } // Fetch ECSD MmcHostInstance->CardInfo.ECSDData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ECSD))); if (MmcHostInstance->CardInfo.ECSDData == NULL) { return EFI_OUT_OF_RESOURCES; } Status = Host->SendCommand (Host, MMC_CMD8, 0); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status)); } Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)MmcHostInstance->CardInfo.ECSDData); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status)); goto FreePageExit; } // Make sure device exiting data mode do { Status = EmmcGetDeviceState (MmcHostInstance, &State); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status)); goto FreePageExit; } } while (State == EMMC_DATA_STATE); // Set up media Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN; Media->ReadOnly = MmcHostInstance->CardInfo.CSDData.PERM_WRITE_PROTECT; Media->LogicalBlocksPerPhysicalBlock = 1; Media->IoAlign = 4; // Compute last block using bits [215:212] of the ECSD Media->LastBlock = MmcHostInstance->CardInfo.ECSDData->SECTOR_COUNT - 1; // eMMC isn't supposed to report this for // Cards <2GB in size, but the model does. // Setup card type MmcHostInstance->CardInfo.CardType = EMMC_CARD; return EFI_SUCCESS; FreePageExit: FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD))); return Status; }
/** This function uses policy data from the platform to determine what operating system or system utility should be loaded and invoked. This function call also optionally make the use of user input to determine the operating system or system utility to be loaded and invoked. When the DXE Core has dispatched all the drivers on the dispatch queue, this function is called. This function will attempt to connect the boot devices required to load and invoke the selected operating system or system utility. During this process, additional firmware volumes may be discovered that may contain addition DXE drivers that can be dispatched by the DXE Core. If a boot device cannot be fully connected, this function calls the DXE Service Dispatch() to allow the DXE drivers from any newly discovered firmware volumes to be dispatched. Then the boot device connection can be attempted again. If the same boot device connection operation fails twice in a row, then that boot device has failed, and should be skipped. This function should never return. @param This The EFI_BDS_ARCH_PROTOCOL instance. @return None. **/ VOID EFIAPI BdsEntry ( IN EFI_BDS_ARCH_PROTOCOL *This ) { UINTN Size; EFI_STATUS Status; UINT16 *BootNext; UINTN BootNextSize; CHAR16 BootVariableName[9]; EFI_EVENT EndOfDxeEvent; VOID *NewBase; // // Signal EndOfDxe PI Event // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, EmptyCallbackFunction, NULL, &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent ); if (!EFI_ERROR (Status)) { gBS->SignalEvent (EndOfDxeEvent); } PERF_END (NULL, "DXE", NULL, 0); OemPostEndIndicator(); //?им1??и▓бф?иж?б└бзиви┤и║б└1?б└и╣бд?бу?бъ?ж╠б└ижи║??2G?и▓бф?и║б└бъ??и▓бф?2?1?ио?бъ??ик?ив??HOB?D //memory reserved идидDикимивижy?asystem memory идидDик NewBase = AllocatePages (EFI_SIZE_TO_PAGES(SIZE_2GB)); if (NULL == NewBase) { DEBUG ((EFI_D_ERROR, "There are not enough memory space..........\n")); } else { FreePages(NewBase,EFI_SIZE_TO_PAGES(SIZE_2GB)); } // // Declare the Firmware Vendor // if (FixedPcdGetPtr(PcdFirmwareVendor) != NULL) { Size = 0x100; gST->FirmwareVendor = AllocateRuntimePool (Size); ASSERT (gST->FirmwareVendor != NULL); UnicodeSPrint (gST->FirmwareVendor, Size, L"%a EFI %a %a", PcdGetPtr(PcdFirmwareVendor), __DATE__, __TIME__); } // // Fixup Table CRC after we updated Firmware Vendor // gST->Hdr.CRC32 = 0; Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { //for fortify } // If BootNext environment variable is defined then we just load it ! BootNextSize = sizeof(UINT16); Status = GetGlobalEnvironmentVariable (L"BootNext", NULL, &BootNextSize, (VOID**)&BootNext); if (!EFI_ERROR(Status)) { ASSERT(BootNextSize == sizeof(UINT16)); // Generate the requested Boot Entry variable name UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", *BootNext); // Set BootCurrent variable gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, BootNextSize, BootNext); FreePool (BootNext); // Start the requested Boot Entry Status = BdsStartBootOption (BootVariableName); if (Status != EFI_NOT_FOUND) { // BootNext has not been succeeded launched if (EFI_ERROR(Status)) { Print(L"Fail to start BootNext.\n"); } // Delete the BootNext environment variable gRT->SetVariable (L"BootNext", &gEfiGlobalVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL); } // Clear BootCurrent variable gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL); } // If Boot Order does not exist then create a default entry DefineDefaultBootEntries (); // Now we need to setup the EFI System Table with information about the console devices. InitializeConsole (); // // Update the CRC32 in the EFI System Table header // gST->Hdr.CRC32 = 0; Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { //for fortify } // Timer before initiating the default boot selection StartDefaultBootOnTimeout (); Status = VerifyBootLineEntry (); if(EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR,"Input Password Error, Boot failed!\n")); return; } // Start the Boot Menu Status = BootMenuMain (); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { //for fortify } }
EFI_STATUS EFIAPI InitializeQemuRamfb ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_DEVICE_PATH_PROTOCOL *RamfbDevicePath; EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; VOID *DevicePath; VENDOR_DEVICE_PATH VendorDeviceNode; ACPI_ADR_DEVICE_PATH AcpiDeviceNode; EFI_STATUS Status; EFI_PHYSICAL_ADDRESS FbBase; UINTN FbSize, MaxFbSize, Pages; UINTN FwCfgSize; UINTN Index; if (!QemuFwCfgIsAvailable ()) { DEBUG ((DEBUG_INFO, "Ramfb: no FwCfg\n")); return EFI_NOT_FOUND; } Status = QemuFwCfgFindFile ("etc/ramfb", &mRamfbFwCfgItem, &FwCfgSize); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } if (FwCfgSize != sizeof (RAMFB_CONFIG)) { DEBUG ((DEBUG_ERROR, "Ramfb: FwCfg size mismatch (expected %lu, got %lu)\n", (UINT64)sizeof (RAMFB_CONFIG), (UINT64)FwCfgSize)); return EFI_PROTOCOL_ERROR; } MaxFbSize = 0; for (Index = 0; Index < ARRAY_SIZE (mQemuRamfbModeInfo); Index++) { mQemuRamfbModeInfo[Index].PixelsPerScanLine = mQemuRamfbModeInfo[Index].HorizontalResolution; mQemuRamfbModeInfo[Index].PixelFormat = PixelBlueGreenRedReserved8BitPerColor; FbSize = RAMFB_BPP * mQemuRamfbModeInfo[Index].HorizontalResolution * mQemuRamfbModeInfo[Index].VerticalResolution; if (MaxFbSize < FbSize) { MaxFbSize = FbSize; } DEBUG ((DEBUG_INFO, "Ramfb: Mode %lu: %ux%u, %lu kB\n", (UINT64)Index, mQemuRamfbModeInfo[Index].HorizontalResolution, mQemuRamfbModeInfo[Index].VerticalResolution, (UINT64)(FbSize / 1024))); } Pages = EFI_SIZE_TO_PAGES (MaxFbSize); MaxFbSize = EFI_PAGES_TO_SIZE (Pages); FbBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateReservedPages (Pages); if (FbBase == 0) { DEBUG ((DEBUG_ERROR, "Ramfb: memory allocation failed\n")); return EFI_OUT_OF_RESOURCES; } DEBUG ((DEBUG_INFO, "Ramfb: Framebuffer at 0x%lx, %lu kB, %lu pages\n", (UINT64)FbBase, (UINT64)(MaxFbSize / 1024), (UINT64)Pages)); mQemuRamfbMode.FrameBufferSize = MaxFbSize; mQemuRamfbMode.FrameBufferBase = FbBase; // // 800 x 600 // QemuRamfbGraphicsOutputSetMode (&mQemuRamfbGraphicsOutput, 1); // // ramfb vendor devpath // VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH; VendorDeviceNode.Header.SubType = HW_VENDOR_DP; CopyGuid (&VendorDeviceNode.Guid, &gQemuRamfbGuid); SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH)); RamfbDevicePath = AppendDevicePathNode (NULL, (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode); if (RamfbDevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto FreeFramebuffer; } Status = gBS->InstallMultipleProtocolInterfaces ( &mRamfbHandle, &gEfiDevicePathProtocolGuid, RamfbDevicePath, NULL ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ramfb: install Ramfb Vendor DevicePath failed: %r\n", Status)); goto FreeRamfbDevicePath; } // // gop devpath + protocol // AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR ( 1, // DeviceIdScheme 0, // HeadId 0, // NonVgaOutput 1, // BiosCanDetect 0, // VendorInfo ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, // Type 0, // Port 0 // Index ); SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); GopDevicePath = AppendDevicePathNode (RamfbDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode); if (GopDevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto FreeRamfbHandle; } Status = gBS->InstallMultipleProtocolInterfaces ( &mGopHandle, &gEfiDevicePathProtocolGuid, GopDevicePath, &gEfiGraphicsOutputProtocolGuid, &mQemuRamfbGraphicsOutput, NULL ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ramfb: install GOP DevicePath failed: %r\n", Status)); goto FreeGopDevicePath; } Status = gBS->OpenProtocol ( mRamfbHandle, &gEfiDevicePathProtocolGuid, &DevicePath, gImageHandle, mGopHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ramfb: OpenProtocol failed: %r\n", Status)); goto FreeGopHandle; } return EFI_SUCCESS; FreeGopHandle: gBS->UninstallMultipleProtocolInterfaces ( mGopHandle, &gEfiDevicePathProtocolGuid, GopDevicePath, &gEfiGraphicsOutputProtocolGuid, &mQemuRamfbGraphicsOutput, NULL ); FreeGopDevicePath: FreePool (GopDevicePath); FreeRamfbHandle: gBS->UninstallMultipleProtocolInterfaces ( mRamfbHandle, &gEfiDevicePathProtocolGuid, RamfbDevicePath, NULL ); FreeRamfbDevicePath: FreePool (RamfbDevicePath); FreeFramebuffer: FreePages ((VOID*)(UINTN)mQemuRamfbMode.FrameBufferBase, Pages); return Status; }
/** Load a given Framework SMM driver into SMRAM and invoke its entry point. @param[in] ParentImageHandle Parent Image Handle. @param[in] FilePath Location of the image to be installed as the handler. @param[in] SourceBuffer Optional source buffer in case the image file is in memory. @param[in] SourceSize Size of the source image file, if in memory. @param[out] ImageHandle The handle that the base driver uses to decode the handler. Unique among SMM handlers only, not unique across DXE/EFI. @retval EFI_SUCCESS The operation was successful. @retval EFI_OUT_OF_RESOURCES There were no additional SMRAM resources to load the handler @retval EFI_UNSUPPORTED Can not find its copy in normal memory. @retval EFI_INVALID_PARAMETER The handlers was not the correct image type **/ EFI_STATUS LoadImage ( IN EFI_HANDLE ParentImageHandle, IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN VOID *SourceBuffer, IN UINTN SourceSize, OUT EFI_HANDLE *ImageHandle ) { EFI_STATUS Status; UINTN PageCount; UINTN OrgPageCount; EFI_PHYSICAL_ADDRESS DstBuffer; if (FilePath == NULL || ImageHandle == NULL) { return EFI_INVALID_PARAMETER; } PageCount = 1; do { OrgPageCount = PageCount; DstBuffer = (UINTN)-1; Status = gSmst->SmmAllocatePages ( AllocateMaxAddress, EfiRuntimeServicesCode, PageCount, &DstBuffer ); if (EFI_ERROR (Status)) { return Status; } Status = mLoadPe32Image->LoadPeImage ( mLoadPe32Image, ParentImageHandle, FilePath, SourceBuffer, SourceSize, DstBuffer, &PageCount, ImageHandle, NULL, EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE ); if (EFI_ERROR (Status)) { FreePages ((VOID *)(UINTN)DstBuffer, OrgPageCount); } } while (Status == EFI_BUFFER_TOO_SMALL); if (!EFI_ERROR (Status)) { /// /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point /// mFrameworkSmst->SmmStartupThisAp = gSmst->SmmStartupThisAp; mFrameworkSmst->NumberOfCpus = mNumberOfProcessors; mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu; Status = gBS->StartImage (*ImageHandle, NULL, NULL); if (EFI_ERROR (Status)) { mLoadPe32Image->UnLoadPeImage (mLoadPe32Image, *ImageHandle); *ImageHandle = NULL; FreePages ((VOID *)(UINTN)DstBuffer, PageCount); } } return Status; }
DynamicStack::~DynamicStack() { FreePages(); }
EFI_STATUS MmCoreFfsFindMmDriver ( IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader ) /*++ Routine Description: Given the pointer to the Firmware Volume Header find the MM driver and return it's PE32 image. Arguments: FwVolHeader - Pointer to memory mapped FV Returns: other - Failure --*/ { EFI_STATUS Status; EFI_STATUS DepexStatus; EFI_FFS_FILE_HEADER *FileHeader; EFI_FV_FILETYPE FileType; VOID *Pe32Data; UINTN Pe32DataSize; VOID *Depex; UINTN DepexSize; UINTN Index; EFI_COMMON_SECTION_HEADER *Section; VOID *SectionData; UINTN SectionDataSize; UINT32 DstBufferSize; VOID *ScratchBuffer; UINT32 ScratchBufferSize; VOID *DstBuffer; UINT16 SectionAttribute; UINT32 AuthenticationStatus; EFI_FIRMWARE_VOLUME_HEADER *InnerFvHeader; DEBUG ((DEBUG_INFO, "MmCoreFfsFindMmDriver - 0x%x\n", FwVolHeader)); if (FvHasBeenProcessed (FwVolHeader)) { return EFI_SUCCESS; } FvIsBeingProcesssed (FwVolHeader); // // First check for encapsulated compressed firmware volumes // FileHeader = NULL; do { Status = FfsFindNextFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, FwVolHeader, &FileHeader); if (EFI_ERROR (Status)) { break; } Status = FfsFindSectionData (EFI_SECTION_GUID_DEFINED, FileHeader, &SectionData, &SectionDataSize); if (EFI_ERROR (Status)) { break; } Section = (EFI_COMMON_SECTION_HEADER *)(FileHeader + 1); Status = ExtractGuidedSectionGetInfo (Section, &DstBufferSize, &ScratchBufferSize, &SectionAttribute); if (EFI_ERROR (Status)) { break; } // // Allocate scratch buffer // ScratchBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); if (ScratchBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } // // Allocate destination buffer, extra one page for adjustment // DstBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); if (DstBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } // // Call decompress function // Status = ExtractGuidedSectionDecode (Section, &DstBuffer, ScratchBuffer, &AuthenticationStatus); FreePages (ScratchBuffer, EFI_SIZE_TO_PAGES (ScratchBufferSize)); if (EFI_ERROR (Status)) { goto FreeDstBuffer; } DEBUG ((DEBUG_INFO, "Processing compressed firmware volume (AuthenticationStatus == %x)\n", AuthenticationStatus)); Status = FindFfsSectionInSections (DstBuffer, DstBufferSize, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, &Section); if (EFI_ERROR (Status)) { goto FreeDstBuffer; } InnerFvHeader = (VOID *)(Section + 1); Status = MmCoreFfsFindMmDriver (InnerFvHeader); if (EFI_ERROR (Status)) { goto FreeDstBuffer; } } while (TRUE); for (Index = 0; Index < sizeof (mMmFileTypes) / sizeof (mMmFileTypes[0]); Index++) { DEBUG ((DEBUG_INFO, "Check MmFileTypes - 0x%x\n", mMmFileTypes[Index])); FileType = mMmFileTypes[Index]; FileHeader = NULL; do { Status = FfsFindNextFile (FileType, FwVolHeader, &FileHeader); if (!EFI_ERROR (Status)) { Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, &Pe32Data, &Pe32DataSize); DEBUG ((DEBUG_INFO, "Find PE data - 0x%x\n", Pe32Data)); DepexStatus = FfsFindSectionData (EFI_SECTION_MM_DEPEX, FileHeader, &Depex, &DepexSize); if (!EFI_ERROR (DepexStatus)) { MmAddToDriverList (FwVolHeader, Pe32Data, Pe32DataSize, Depex, DepexSize, &FileHeader->Name); } } } while (!EFI_ERROR (Status)); } return EFI_SUCCESS; FreeDstBuffer: FreePages (DstBuffer, EFI_SIZE_TO_PAGES (DstBufferSize)); return Status; }
/** Allocates one or more 4KB pages of a certain memory type at a specified alignment. Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned. If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. If Alignment is not a power of two and Alignment is not zero, then ASSERT(). @param MemoryType The type of memory to allocate. @param Pages The number of 4 KB pages to allocate. @param Alignment The requested alignment of the allocation. Must be a power of two. If Alignment is zero, then byte alignment is used. @return A pointer to the allocated buffer or NULL if allocation fails. **/ VOID * InternalAllocateAlignedPages ( IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, IN UINTN Alignment ) { EFI_STATUS Status; VOID *Memory; UINTN AlignedMemory; UINTN AlignmentMask; UINTN UnalignedPages; UINTN RealPages; // // Alignment must be a power of two or zero. // ASSERT ((Alignment & (Alignment - 1)) == 0); if (Pages == 0) { return NULL; } if (Alignment > EFI_PAGE_SIZE) { // // Caculate the total number of pages since alignment is larger than page size. // AlignmentMask = Alignment - 1; RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); // // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. // ASSERT (RealPages > Pages); Memory = gEmuThunk->Valloc (Pages * EFI_PAGE_SIZE); if (Memory != NULL) { return NULL; } AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory); if (UnalignedPages > 0) { // // Free first unaligned page(s). // FreePages (Memory, UnalignedPages); } Memory = (VOID *) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages)); UnalignedPages = RealPages - Pages - UnalignedPages; if (UnalignedPages > 0) { // // Free last unaligned page(s). // FreePages (Memory, UnalignedPages); } } else { // // Do not over-allocate pages in this case. // Memory = gEmuThunk->Valloc (Pages * EFI_PAGE_SIZE); if (Memory != NULL) { return NULL; } AlignedMemory = (UINTN) Memory; } return (VOID *) AlignedMemory; }
/** Exit the EBL. If the command processor sees EFI_ABORTED return status it will exit the EBL. Argv[0] - "exit" @param Argc Number of command arguments in Argv @param Argv Array of strings that represent the parsed command line. Argv[0] is the command name @return EFI_ABORTED **/ EFI_STATUS EFIAPI EblExitCmd ( IN UINTN Argc, IN CHAR8 **Argv ) { EFI_STATUS Status; UINTN MemoryMapSize; EFI_MEMORY_DESCRIPTOR *MemoryMap; UINTN MapKey; UINTN DescriptorSize; UINT32 DescriptorVersion; UINTN Pages; if (Argc > 1) { if (AsciiStriCmp (Argv[1], "efi") != 0) { return EFI_ABORTED; } } else if (Argc == 1) { return EFI_ABORTED; } MemoryMap = NULL; MemoryMapSize = 0; do { Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); if (Status == EFI_BUFFER_TOO_SMALL) { Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1; MemoryMap = AllocatePages (Pages); // // Get System MemoryMap // Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); // Don't do anything between the GetMemoryMap() and ExitBootServices() if (!EFI_ERROR (Status)) { Status = gBS->ExitBootServices (gImageHandle, MapKey); if (EFI_ERROR (Status)) { FreePages (MemoryMap, Pages); MemoryMap = NULL; MemoryMapSize = 0; } } } } while (EFI_ERROR (Status)); // // At this point it is very dangerous to do things EFI as most of EFI is now gone. // This command is useful if you are working with a debugger as it will shutdown // DMA and other things that could break a soft resets. // CpuDeadLoop (); // Should never get here, but makes the compiler happy return EFI_ABORTED; }
EFI_STATUS TryRunningQemuKernel ( VOID ) { EFI_STATUS Status; UINTN KernelSize; UINTN KernelInitialSize; VOID *KernelBuf; UINTN SetupSize; VOID *SetupBuf; UINTN CommandLineSize; CHAR8 *CommandLine; UINTN InitrdSize; VOID* InitrdData; SetupBuf = NULL; SetupSize = 0; KernelBuf = NULL; KernelInitialSize = 0; CommandLine = NULL; CommandLineSize = 0; InitrdData = NULL; InitrdSize = 0; if (!QemuFwCfgIsAvailable ()) { return EFI_NOT_FOUND; } QemuFwCfgSelectItem (QemuFwCfgItemKernelSize); KernelSize = (UINTN) QemuFwCfgRead64 (); QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupSize); SetupSize = (UINTN) QemuFwCfgRead64 (); if (KernelSize == 0 || SetupSize == 0) { DEBUG ((EFI_D_INFO, "qemu -kernel was not used.\n")); return EFI_NOT_FOUND; } SetupBuf = LoadLinuxAllocateKernelSetupPages (EFI_SIZE_TO_PAGES (SetupSize)); if (SetupBuf == NULL) { DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel setup!\n")); return EFI_OUT_OF_RESOURCES; } DEBUG ((EFI_D_INFO, "Setup size: 0x%x\n", (UINT32) SetupSize)); DEBUG ((EFI_D_INFO, "Reading kernel setup image ...")); QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupData); QemuFwCfgReadBytes (SetupSize, SetupBuf); DEBUG ((EFI_D_INFO, " [done]\n")); Status = LoadLinuxCheckKernelSetup (SetupBuf, SetupSize); if (EFI_ERROR (Status)) { goto FreeAndReturn; } Status = LoadLinuxInitializeKernelSetup (SetupBuf); if (EFI_ERROR (Status)) { goto FreeAndReturn; } KernelInitialSize = LoadLinuxGetKernelSize (SetupBuf, KernelSize); if (KernelInitialSize == 0) { Status = EFI_UNSUPPORTED; goto FreeAndReturn; } KernelBuf = LoadLinuxAllocateKernelPages ( SetupBuf, EFI_SIZE_TO_PAGES (KernelInitialSize)); if (KernelBuf == NULL) { DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel!\n")); Status = EFI_OUT_OF_RESOURCES; goto FreeAndReturn; } DEBUG ((EFI_D_INFO, "Kernel size: 0x%x\n", (UINT32) KernelSize)); DEBUG ((EFI_D_INFO, "Reading kernel image ...")); QemuFwCfgSelectItem (QemuFwCfgItemKernelData); QemuFwCfgReadBytes (KernelSize, KernelBuf); DEBUG ((EFI_D_INFO, " [done]\n")); QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize); CommandLineSize = (UINTN) QemuFwCfgRead64 (); if (CommandLineSize > 0) { CommandLine = LoadLinuxAllocateCommandLinePages ( EFI_SIZE_TO_PAGES (CommandLineSize)); QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData); QemuFwCfgReadBytes (CommandLineSize, CommandLine); } else { CommandLine = NULL; } Status = LoadLinuxSetCommandLine (SetupBuf, CommandLine); if (EFI_ERROR (Status)) { goto FreeAndReturn; } QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize); InitrdSize = (UINTN) QemuFwCfgRead64 (); if (InitrdSize > 0) { InitrdData = LoadLinuxAllocateInitrdPages ( SetupBuf, EFI_SIZE_TO_PAGES (InitrdSize) ); DEBUG ((EFI_D_INFO, "Initrd size: 0x%x\n", (UINT32) InitrdSize)); DEBUG ((EFI_D_INFO, "Reading initrd image ...")); QemuFwCfgSelectItem (QemuFwCfgItemInitrdData); QemuFwCfgReadBytes (InitrdSize, InitrdData); DEBUG ((EFI_D_INFO, " [done]\n")); } else { InitrdData = NULL; } Status = LoadLinuxSetInitrd (SetupBuf, InitrdData, InitrdSize); if (EFI_ERROR (Status)) { goto FreeAndReturn; } Status = LoadLinux (KernelBuf, SetupBuf); FreeAndReturn: if (SetupBuf != NULL) { FreePages (SetupBuf, EFI_SIZE_TO_PAGES (SetupSize)); } if (KernelBuf != NULL) { FreePages (KernelBuf, EFI_SIZE_TO_PAGES (KernelInitialSize)); } if (CommandLine != NULL) { FreePages (CommandLine, EFI_SIZE_TO_PAGES (CommandLineSize)); } if (InitrdData != NULL) { FreePages (InitrdData, EFI_SIZE_TO_PAGES (InitrdSize)); } return Status; }
/** Install ACPI Firmware Performance Data Table (FPDT). @return Status code. **/ EFI_STATUS InstallFirmwarePerformanceDataTable ( VOID ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; UINTN Size; UINT8 *SmmBootRecordCommBuffer; EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader; SMM_BOOT_RECORD_COMMUNICATE *SmmCommData; UINTN CommSize; UINTN BootPerformanceDataSize; UINT8 *BootPerformanceData; EFI_SMM_COMMUNICATION_PROTOCOL *Communication; FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable; // // Get AcpiTable Protocol. // Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol); if (EFI_ERROR (Status)) { return Status; } // // Collect boot records from SMM drivers. // SmmBootRecordCommBuffer = NULL; SmmCommData = NULL; Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication); if (!EFI_ERROR (Status)) { // // Initialize communicate buffer // SmmBootRecordCommBuffer = AllocateZeroPool (SMM_BOOT_RECORD_COMM_SIZE); ASSERT (SmmBootRecordCommBuffer != NULL); SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER*)SmmBootRecordCommBuffer; SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)SmmCommBufferHeader->Data; ZeroMem((UINT8*)SmmCommData, sizeof(SMM_BOOT_RECORD_COMMUNICATE)); CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid); SmmCommBufferHeader->MessageLength = sizeof(SMM_BOOT_RECORD_COMMUNICATE); CommSize = SMM_BOOT_RECORD_COMM_SIZE; // // Get the size of boot records. // SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE; SmmCommData->BootRecordData = NULL; Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize); ASSERT_EFI_ERROR (Status); if (!EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) { // // Get all boot records // SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA; SmmCommData->BootRecordData = AllocateZeroPool(SmmCommData->BootRecordSize); ASSERT (SmmCommData->BootRecordData != NULL); Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize); ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR(SmmCommData->ReturnStatus); } } // // Prepare memory for Boot Performance table. // Boot Performance table includes BasicBoot record, and one or more appended Boot Records. // BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize); if (SmmCommData != NULL) { BootPerformanceDataSize += SmmCommData->BootRecordSize; } // // Try to allocate the same runtime buffer as last time boot. // ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable)); Size = sizeof (PerformanceVariable); Status = gRT->GetVariable ( EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME, &gEfiFirmwarePerformanceGuid, NULL, &Size, &PerformanceVariable ); if (!EFI_ERROR (Status)) { Status = gBS->AllocatePages ( AllocateAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES (BootPerformanceDataSize), &PerformanceVariable.BootPerformanceTablePointer ); if (!EFI_ERROR (Status)) { mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.BootPerformanceTablePointer; } } if (mAcpiBootPerformanceTable == NULL) { // // Fail to allocate at specified address, continue to allocate at any address. // mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize); } DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable)); if (mAcpiBootPerformanceTable == NULL) { if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) { FreePool (SmmCommData->BootRecordData); } if (SmmBootRecordCommBuffer != NULL) { FreePool (SmmBootRecordCommBuffer); } if (mAcpiS3PerformanceTable != NULL) { FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE))); } return EFI_OUT_OF_RESOURCES; } // // Prepare Boot Performance Table. // BootPerformanceData = (UINT8 *) mAcpiBootPerformanceTable; // // Fill Basic Boot record to Boot Performance Table. // CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate)); BootPerformanceData = BootPerformanceData + mAcpiBootPerformanceTable->Header.Length; // // Fill Boot records from boot drivers. // CopyMem (BootPerformanceData, mBootRecordBuffer, mBootRecordSize); mAcpiBootPerformanceTable->Header.Length += mBootRecordSize; BootPerformanceData = BootPerformanceData + mBootRecordSize; if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) { // // Fill Boot records from SMM drivers. // CopyMem (BootPerformanceData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize); FreePool (SmmCommData->BootRecordData); mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmCommData->BootRecordSize); BootPerformanceData = BootPerformanceData + SmmCommData->BootRecordSize; } if (SmmBootRecordCommBuffer != NULL) { FreePool (SmmBootRecordCommBuffer); } // // Save Boot Performance Table address to Variable for use in S4 resume. // PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiBootPerformanceTable; // // Update Boot Performance Table Pointer in template. // mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable; // // Save S3 Performance Table address to Variable for use in S4 resume. // PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable; // // Update S3 Performance Table Pointer in template. // mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) (UINTN) mAcpiS3PerformanceTable; // // Save Runtime Performance Table pointers to Variable. // Status = gRT->SetVariable ( EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME, &gEfiFirmwarePerformanceGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof (PerformanceVariable), &PerformanceVariable ); ASSERT_EFI_ERROR (Status); // // Publish Firmware Performance Data Table. // FpdtAcpiTableChecksum ((UINT8 *) &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length); Status = AcpiTableProtocol->InstallAcpiTable ( AcpiTableProtocol, &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length, &mFirmwarePerformanceTableTemplateKey ); if (EFI_ERROR (Status)) { FreePages (mAcpiBootPerformanceTable, EFI_SIZE_TO_PAGES (BootPerformanceDataSize)); if (mAcpiS3PerformanceTable != NULL) { FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE))); } mAcpiBootPerformanceTable = NULL; mAcpiS3PerformanceTable = NULL; return Status; } // // Free temp Boot record, and update Boot Record to point to Basic Boot performance table. // if (mBootRecordBuffer != NULL) { FreePool (mBootRecordBuffer); } mBootRecordBuffer = (UINT8 *) mAcpiBootPerformanceTable; mBootRecordSize = mAcpiBootPerformanceTable->Header.Length; mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize); return EFI_SUCCESS; }
/** Sends SD command to an SD card that is attached to the SD controller. The PassThru() function sends the SD command specified by Packet to the SD card specified by Slot. If Packet is successfully sent to the SD card, then EFI_SUCCESS is returned. If a device error occurs while sending the Packet, then EFI_DEVICE_ERROR is returned. If Slot is not in a valid range for the SD controller, then EFI_INVALID_PARAMETER is returned. If Packet defines a data command but both InDataBuffer and OutDataBuffer are NULL, EFI_INVALID_PARAMETER is returned. @param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. @param[in] Slot The slot number of the SD card to send the command to. @param[in,out] Packet A pointer to the SD command data structure. @param[in] Event If Event is NULL, blocking I/O is performed. If Event is not NULL, then nonblocking I/O is performed, and Event will be signaled when the Packet completes. @retval EFI_SUCCESS The SD Command Packet was sent by the host. @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SD command Packet. @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the Packet is invalid. @retval EFI_INVALID_PARAMETER Packet defines a data command but both InDataBuffer and OutDataBuffer are NULL. @retval EFI_NO_MEDIA SD Device not present in the Slot. @retval EFI_UNSUPPORTED The command described by the SD Command Packet is not supported by the host controller. @retval EFI_BAD_BUFFER_SIZE The InTransferLength or OutTransferLength exceeds the limit supported by SD card ( i.e. if the number of bytes exceed the Last LBA). **/ EFI_STATUS EFIAPI SdMmcPassThruPassThru ( IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, IN UINT8 Slot, IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, IN EFI_EVENT Event OPTIONAL ) { EFI_STATUS Status; SD_MMC_HC_PRIVATE_DATA *Private; SD_MMC_HC_TRB *Trb; EFI_TPL OldTpl; if ((This == NULL) || (Packet == NULL)) { return EFI_INVALID_PARAMETER; } if ((Packet->SdMmcCmdBlk == NULL) || (Packet->SdMmcStatusBlk == NULL)) { return EFI_INVALID_PARAMETER; } if ((Packet->OutDataBuffer == NULL) && (Packet->OutTransferLength != 0)) { return EFI_INVALID_PARAMETER; } if ((Packet->InDataBuffer == NULL) && (Packet->InTransferLength != 0)) { return EFI_INVALID_PARAMETER; } Private = SD_MMC_HC_PRIVATE_FROM_THIS (This); if (!Private->Slot[Slot].Enable) { return EFI_INVALID_PARAMETER; } if (!Private->Slot[Slot].MediaPresent) { return EFI_NO_MEDIA; } if (!Private->Slot[Slot].Initialized) { return EFI_DEVICE_ERROR; } Trb = SdMmcCreateTrb (Private, Slot, Packet, Event); if (Trb == NULL) { return EFI_OUT_OF_RESOURCES; } // // Immediately return for async I/O. // if (Event != NULL) { return EFI_SUCCESS; } // // Wait async I/O list is empty before execute sync I/O operation. // while (TRUE) { OldTpl = gBS->RaiseTPL (TPL_NOTIFY); if (IsListEmpty (&Private->Queue)) { gBS->RestoreTPL (OldTpl); break; } gBS->RestoreTPL (OldTpl); } Status = SdMmcWaitTrbEnv (Private, Trb); if (EFI_ERROR (Status)) { goto Done; } Status = SdMmcExecTrb (Private, Trb); if (EFI_ERROR (Status)) { goto Done; } Status = SdMmcWaitTrbResult (Private, Trb); if (EFI_ERROR (Status)) { goto Done; } Done: if ((Trb != NULL) && (Trb->AdmaDesc != NULL)) { FreePages (Trb->AdmaDesc, Trb->AdmaPages); } if (Trb != NULL) { FreePool (Trb); } return Status; }
/** Initialize DMA protection. @param VTdInfo The VTd engine context information. @retval EFI_SUCCESS the DMA protection is initialized. @retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection. **/ EFI_STATUS InitDmaProtection ( IN VTD_INFO *VTdInfo ) { EFI_STATUS Status; UINT32 LowMemoryAlignment; UINT64 HighMemoryAlignment; UINTN MemoryAlignment; UINTN LowBottom; UINTN LowTop; UINTN HighBottom; UINT64 HighTop; DMA_BUFFER_INFO *DmaBufferInfo; VOID *Hob; EFI_PEI_PPI_DESCRIPTOR *OldDescriptor; EDKII_IOMMU_PPI *OldIoMmuPpi; Hob = GetFirstGuidHob (&mDmaBufferInfoGuid); DmaBufferInfo = GET_GUID_HOB_DATA(Hob); DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize)); LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask); HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask); if (LowMemoryAlignment < HighMemoryAlignment) { MemoryAlignment = (UINTN)HighMemoryAlignment; } else { MemoryAlignment = LowMemoryAlignment; } ASSERT (DmaBufferInfo->DmaBufferSize == ALIGN_VALUE(DmaBufferInfo->DmaBufferSize, MemoryAlignment)); DmaBufferInfo->DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferInfo->DmaBufferSize), MemoryAlignment); ASSERT (DmaBufferInfo->DmaBufferBase != 0); if (DmaBufferInfo->DmaBufferBase == 0) { DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n")); return EFI_OUT_OF_RESOURCES; } DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase)); DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize; DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase; // // (Re)Install PPI. // Status = PeiServicesLocatePpi ( &gEdkiiIoMmuPpiGuid, 0, &OldDescriptor, (VOID **) &OldIoMmuPpi ); if (!EFI_ERROR (Status)) { Status = PeiServicesReInstallPpi (OldDescriptor, &mIoMmuPpiList); } else { Status = PeiServicesInstallPpi (&mIoMmuPpiList); } ASSERT_EFI_ERROR (Status); LowBottom = 0; LowTop = DmaBufferInfo->DmaBufferBase; HighBottom = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize; HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1); Status = SetDmaProtectedRange ( VTdInfo, VTdInfo->EngineMask, (UINT32)LowBottom, (UINT32)(LowTop - LowBottom), HighBottom, HighTop - HighBottom ); if (EFI_ERROR(Status)) { FreePages ((VOID *)DmaBufferInfo->DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferInfo->DmaBufferSize)); } return Status; }
/** Allocates pages that are suitable for an OperationBusMasterCommonBuffer or OperationBusMasterCommonBuffer64 mapping. @param This The protocol instance pointer. @param Type This parameter is not used and must be ignored. @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData. @param Pages The number of pages to allocate. @param HostAddress A pointer to store the base system memory address of the allocated range. @param Attributes The requested bit mask of attributes for the allocated range. @retval EFI_SUCCESS The requested memory pages were allocated. @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are MEMORY_WRITE_COMBINE and MEMORY_CACHED. @retval EFI_INVALID_PARAMETER One or more parameters are invalid. @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. **/ EFI_STATUS EFIAPI IoMmuAllocateBuffer ( IN EDKII_IOMMU_PROTOCOL *This, IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, IN OUT VOID **HostAddress, IN UINT64 Attributes ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS PhysicalAddress; VOID *StashBuffer; UINTN CommonBufferPages; COMMON_BUFFER_HEADER *CommonBufferHeader; // // Validate Attributes // if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) { return EFI_UNSUPPORTED; } // // Check for invalid inputs // if (HostAddress == NULL) { return EFI_INVALID_PARAMETER; } // // The only valid memory types are EfiBootServicesData and // EfiRuntimeServicesData // if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { return EFI_INVALID_PARAMETER; } // // We'll need a header page for the COMMON_BUFFER_HEADER structure. // if (Pages > MAX_UINTN - 1) { return EFI_OUT_OF_RESOURCES; } CommonBufferPages = Pages + 1; // // Allocate the stash in EfiBootServicesData type memory. // // Map() will temporarily save encrypted data in the stash for // BusMasterCommonBuffer[64] operations, so the data can be decrypted to the // original location. // // Unmap() will temporarily save plaintext data in the stash for // BusMasterCommonBuffer[64] operations, so the data can be encrypted to the // original location. // // StashBuffer always resides in encrypted memory. // StashBuffer = AllocatePages (Pages); if (StashBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } PhysicalAddress = (UINTN)-1; if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) { // // Limit allocations to memory below 4GB // PhysicalAddress = SIZE_4GB - 1; } Status = gBS->AllocatePages ( AllocateMaxAddress, MemoryType, CommonBufferPages, &PhysicalAddress ); if (EFI_ERROR (Status)) { goto FreeStashBuffer; } CommonBufferHeader = (VOID *)(UINTN)PhysicalAddress; PhysicalAddress += EFI_PAGE_SIZE; CommonBufferHeader->Signature = COMMON_BUFFER_SIG; CommonBufferHeader->StashBuffer = StashBuffer; *HostAddress = (VOID *)(UINTN)PhysicalAddress; DEBUG (( DEBUG_VERBOSE, "%a Address 0x%Lx Pages 0x%Lx\n", __FUNCTION__, PhysicalAddress, (UINT64)Pages )); return EFI_SUCCESS; FreeStashBuffer: FreePages (StashBuffer, Pages); return Status; }