audk/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Ipf/IpfBootSupport.c

278 lines
8.3 KiB
C

/** @file
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The
full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "LegacyBiosInterface.h"
/**
Assign drive number to legacy HDD drives prior to booting an EFI
aware OS so the OS can access drives without an EFI driver.
Note: BBS compliant drives ARE NOT available until this call by
either shell or EFI.
@param This Protocol instance pointer.
@param BbsCount Number of BBS_TABLE structures
@param BbsTable List BBS entries
@retval EFI_SUCCESS Drive numbers assigned
**/
EFI_STATUS
EFIAPI
LegacyBiosPrepareToBootEfi (
IN EFI_LEGACY_BIOS_PROTOCOL *This,
OUT UINT16 *BbsCount,
OUT BBS_TABLE **BbsTable
)
{
//
// Shadow All Opion ROM
//
LegacyBiosShadowAllLegacyOproms (This);
return EFI_SUCCESS;
}
/**
To boot from an unconventional device like parties and/or execute
HDD diagnostics.
@param This Protocol instance pointer.
@param Attributes How to interpret the other input parameters
@param BbsEntry The 0-based index into the BbsTable for the
parent device.
@param BeerData Pointer to the 128 bytes of ram BEER data.
@param ServiceAreaData Pointer to the 64 bytes of raw Service Area data.
The caller must provide a pointer to the specific
Service Area and not the start all Service Areas.
EFI_INVALID_PARAMETER if error. Does NOT return if no error.
**/
EFI_STATUS
EFIAPI
LegacyBiosBootUnconventionalDevice (
IN EFI_LEGACY_BIOS_PROTOCOL *This,
IN UDC_ATTRIBUTES Attributes,
IN UINTN BbsEntry,
IN VOID *BeerData,
IN VOID *ServiceAreaData
)
{
return EFI_INVALID_PARAMETER;
}
/**
Attempt to legacy boot the BootOption. If the EFI contexted has been
compromised this function will not return.
@param This Protocol instance pointer.
@param BbsDevicePath EFI Device Path from BootXXXX variable.
@param LoadOptionsSize Size of LoadOption in size.
@param LoadOptions LoadOption from BootXXXX variable
@retval EFI_SUCCESS Removable media not present
**/
EFI_STATUS
EFIAPI
LegacyBiosLegacyBoot (
IN EFI_LEGACY_BIOS_PROTOCOL *This,
IN BBS_BBS_DEVICE_PATH *BbsDevicePath,
IN UINT32 LoadOptionsSize,
IN VOID *LoadOptions
)
{
return EFI_UNSUPPORTED;
}
/**
Build the E820 table.
@param Private Legacy BIOS Instance data
@param Size Size of E820 Table
@retval EFI_SUCCESS It should always work.
**/
EFI_STATUS
LegacyBiosBuildE820 (
IN LEGACY_BIOS_INSTANCE *Private,
OUT UINTN *Size
)
{
*Size = 0;
return EFI_SUCCESS;
}
/**
Get all BBS info
@param This Protocol instance pointer.
@param HddCount Number of HDD_INFO structures
@param HddInfo Onboard IDE controller information
@param BbsCount Number of BBS_TABLE structures
@param BbsTable List BBS entries
@retval EFI_SUCCESS Tables returned
@retval EFI_NOT_FOUND resource not found
@retval EFI_DEVICE_ERROR can not get BBS table
**/
EFI_STATUS
EFIAPI
LegacyBiosGetBbsInfo (
IN EFI_LEGACY_BIOS_PROTOCOL *This,
OUT UINT16 *HddCount,
OUT HDD_INFO **HddInfo,
OUT UINT16 *BbsCount,
OUT BBS_TABLE **BbsTable
)
{
return EFI_UNSUPPORTED;
}
/**
Fill in the standard BDA for Keyboard LEDs
@param This Protocol instance pointer.
@param Leds Current LED status
@retval EFI_SUCCESS It should always work.
**/
EFI_STATUS
EFIAPI
LegacyBiosUpdateKeyboardLedStatus (
IN EFI_LEGACY_BIOS_PROTOCOL *This,
IN UINT8 Leds
)
{
return EFI_UNSUPPORTED;
}
/**
Relocate this image under 4G memory for IPF.
@param ImageHandle Handle of driver image.
@param SystemTable Pointer to system table.
@retval EFI_SUCCESS Image successfully relocated.
@retval EFI_ABORTED Failed to relocate image.
**/
EFI_STATUS
RelocateImageUnder4GIfNeeded (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
UINTN NumberOfPages;
EFI_PHYSICAL_ADDRESS LoadedImageBase;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
EFI_PHYSICAL_ADDRESS MemoryAddress;
EFI_HANDLE NewImageHandle;
Status = gBS->HandleProtocol (
ImageHandle,
&gEfiLoadedImageProtocolGuid,
(VOID *) &LoadedImage
);
if (!EFI_ERROR (Status)) {
LoadedImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) LoadedImage->ImageBase;
if (LoadedImageBase > 0xffffffff) {
NumberOfPages = (UINTN) (DivU64x32(LoadedImage->ImageSize, EFI_PAGE_SIZE) + 1);
//
// Allocate buffer below 4GB here
//
Status = AllocateLegacyMemory (
AllocateMaxAddress,
0x7FFFFFFF,
NumberOfPages, // do we have to convert this to pages??
&MemoryAddress
);
if (EFI_ERROR (Status)) {
return Status;
}
ZeroMem (&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
ImageContext.Handle = (VOID *)(UINTN)LoadedImageBase;
ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
//
// Get information about the image being loaded
//
Status = PeCoffLoaderGetImageInfo (&ImageContext);
if (EFI_ERROR (Status)) {
return Status;
}
ImageContext.ImageAddress = (PHYSICAL_ADDRESS)MemoryAddress;
//
// Align buffer on section boundry
//
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
//
// Load the image to our new buffer
//
Status = PeCoffLoaderLoadImage (&ImageContext);
if (EFI_ERROR (Status)) {
gBS->FreePages (MemoryAddress, NumberOfPages);
return Status;
}
//
// Relocate the image in our new buffer
//
Status = PeCoffLoaderRelocateImage (&ImageContext);
if (EFI_ERROR (Status)) {
gBS->FreePages (MemoryAddress, NumberOfPages);
return Status;
}
//
// Create a new handle with gEfiCallerIdGuid to be used as the ImageHandle fore the reloaded image
//
NewImageHandle = NULL;
Status = gBS->InstallProtocolInterface (
&NewImageHandle,
&gEfiCallerIdGuid,
EFI_NATIVE_INTERFACE,
NULL
);
//
// Flush the instruction cache so the image data is written before we execute it
//
InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
if (EFI_ERROR (Status)) {
gBS->FreePages (MemoryAddress, NumberOfPages);
return Status;
}
//
// return error directly the BS will unload this image
//
return EFI_ABORTED;
}
}
return EFI_SUCCESS;
}