blob: 8586e3368aa5420b931593ec9efff2adc759585c [file] [log] [blame]
/** @file
*
* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
* Copyright (c) 2015, Linaro Limited. All rights reserved.
*
* 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 <Uefi.h>
#include <Pi/PiDxeCis.h>
#include <Library/DebugLib.h>
#include <libfdt.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PrintLib.h>
#include <Guid/Fdt.h>
#include <Protocol/HisiBoardNicProtocol.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/FdtUpdateLib.h>
STATIC
EFI_STATUS
InstallFdtIntoConfigurationTable (
IN VOID* FdtBlob,
IN UINTN FdtSize
)
{
EFI_STATUS Status;
// Check the FDT header is valid. We only make this check in DEBUG mode in case the FDT header change on
// production device and this ASSERT() becomes not valid.
if(!(fdt_check_header (FdtBlob) == 0))
{
DEBUG ((EFI_D_ERROR,"can not find FdtBlob \n"));
return EFI_INVALID_PARAMETER;
}
// Ensure the Size of the Device Tree is smaller than the size of the read file
if(!((UINTN)fdt_totalsize (FdtBlob) <= FdtSize))
{
DEBUG ((EFI_D_ERROR,"FdtBlob <= FdtSize \n"));
return EFI_INVALID_PARAMETER;
}
// Install the FDT into the Configuration Table
Status = gBS->InstallConfigurationTable (&gFdtTableGuid, FdtBlob);
return Status;
}
EFI_STATUS
SetNvramSpace (VOID)
{
EFI_STATUS Status;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR desp = {0};
if (PcdGet64(PcdReservedNvramSize) == 0) {
return EFI_SUCCESS;
}
Status = gDS->GetMemorySpaceDescriptor(PcdGet64(PcdReservedNvramBase),&desp);
if(EFI_ERROR(Status)){
DEBUG ((EFI_D_ERROR,"get memory space error:--------- \n"));
return Status;
}
desp.Attributes |= EFI_MEMORY_RUNTIME | EFI_MEMORY_WB;
Status = gDS->SetMemorySpaceAttributes(PcdGet64(PcdReservedNvramBase),PcdGet64(PcdReservedNvramSize), desp.Attributes);
if(EFI_ERROR(Status)){
DEBUG ((EFI_D_ERROR,"set memory space error:--------- \n"));
return Status;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI UpdateFdt (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable)
{
INTN Error;
VOID* Fdt;
UINT32 Size;
UINTN NewFdtBlobSize;
UINTN NewFdtBlobBase;
EFI_STATUS Status = EFI_SUCCESS;
UINT32 Index = 0;
UINTN FDTConfigTable;
(VOID) SetNvramSpace ();
Fdt = (VOID*)(PcdGet64(FdtFileAddress));
Error = fdt_check_header ((VOID*)(PcdGet64(FdtFileAddress)));
DEBUG ((EFI_D_ERROR,"fdtfileaddress:--------- 0x%lx\n",PcdGet64(FdtFileAddress)));
if (Error != 0)
{
DEBUG ((EFI_D_ERROR,"ERROR: Device Tree header not valid (%a)\n", fdt_strerror(Error)));
return EFI_INVALID_PARAMETER;
}
Size = (UINTN)fdt_totalsize ((VOID*)(PcdGet64(FdtFileAddress)));
NewFdtBlobSize = Size + ADD_FILE_LENGTH;
Status = gBS->AllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES(Size), &NewFdtBlobBase);
if (EFI_ERROR (Status))
{
return EFI_OUT_OF_RESOURCES;
}
(VOID) CopyMem((VOID*)NewFdtBlobBase, Fdt, Size);
Status = EFIFdtUpdate(NewFdtBlobBase);
if (EFI_ERROR (Status))
{
DEBUG((EFI_D_ERROR, "%a(%d):EFIFdtUpdate Fail!\n", __FUNCTION__,__LINE__));
goto EXIT;
}
Status = InstallFdtIntoConfigurationTable ((VOID*)(UINTN)NewFdtBlobBase, NewFdtBlobSize);
DEBUG ((EFI_D_ERROR, "NewFdtBlobBase: 0x%lx NewFdtBlobSize:0x%lx\n",NewFdtBlobBase,NewFdtBlobSize));
if (EFI_ERROR (Status))
{
DEBUG ((EFI_D_ERROR, "installfdtconfiguration table fail():\n"));
goto EXIT;
}
for (Index = 0; Index < gST->NumberOfTableEntries; Index ++)
{
if (CompareGuid (&gFdtTableGuid, &(gST->ConfigurationTable[Index].VendorGuid)))
{
FDTConfigTable = (UINTN)gST->ConfigurationTable[Index].VendorTable;
DEBUG ((EFI_D_ERROR, "FDTConfigTable Address: 0x%lx\n",FDTConfigTable));
break;
}
}
return Status;
EXIT:
gBS->FreePages(NewFdtBlobBase,EFI_SIZE_TO_PAGES(NewFdtBlobSize));
return Status;
}