From d9325c8e4f858abe7b888b21df4bd0a34864492f Mon Sep 17 00:00:00 2001 From: oliviermartin Date: Thu, 22 Sep 2011 22:55:54 +0000 Subject: ArmPkg/BdsLib: Move the code specific to the Atag preparation into a separate file git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12409 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPkg/Library/BdsLib/BdsLinuxAtag.c | 163 +++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 ArmPkg/Library/BdsLib/BdsLinuxAtag.c (limited to 'ArmPkg/Library/BdsLib/BdsLinuxAtag.c') diff --git a/ArmPkg/Library/BdsLib/BdsLinuxAtag.c b/ArmPkg/Library/BdsLib/BdsLinuxAtag.c new file mode 100644 index 0000000000..253cf65f36 --- /dev/null +++ b/ArmPkg/Library/BdsLib/BdsLinuxAtag.c @@ -0,0 +1,163 @@ +/** @file +* +* Copyright (c) 2011, ARM 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 "BdsInternal.h" + +// Point to the current ATAG +STATIC LINUX_ATAG *mLinuxKernelCurrentAtag; + +STATIC +VOID +SetupCoreTag ( + IN UINT32 PageSize + ) +{ + mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_CORE); + mLinuxKernelCurrentAtag->header.type = ATAG_CORE; + + mLinuxKernelCurrentAtag->body.core_tag.flags = 1; /* ensure read-only */ + mLinuxKernelCurrentAtag->body.core_tag.pagesize = PageSize; /* systems PageSize (4k) */ + mLinuxKernelCurrentAtag->body.core_tag.rootdev = 0; /* zero root device (typically overridden from kernel command line )*/ + + // move pointer to next tag + mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag); +} + +STATIC +VOID +SetupMemTag ( + IN UINTN StartAddress, + IN UINT32 Size + ) +{ + mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_MEM); + mLinuxKernelCurrentAtag->header.type = ATAG_MEM; + + mLinuxKernelCurrentAtag->body.mem_tag.start = StartAddress; /* Start of memory chunk for AtagMem */ + mLinuxKernelCurrentAtag->body.mem_tag.size = Size; /* Size of memory chunk for AtagMem */ + + // move pointer to next tag + mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag); +} + +STATIC +VOID +SetupCmdlineTag ( + IN CONST CHAR8 *CmdLine + ) +{ + UINT32 LineLength; + + // Increment the line length by 1 to account for the null string terminator character + LineLength = AsciiStrLen(CmdLine) + 1; + + /* Check for NULL strings. + * Do not insert a tag for an empty CommandLine, don't even modify the tag address pointer. + * Remember, you have at least one null string terminator character. + */ + if(LineLength > 1) { + mLinuxKernelCurrentAtag->header.size = ((UINT32)sizeof(LINUX_ATAG_HEADER) + LineLength + (UINT32)3) >> 2; + mLinuxKernelCurrentAtag->header.type = ATAG_CMDLINE; + + /* place CommandLine into tag */ + AsciiStrCpy(mLinuxKernelCurrentAtag->body.cmdline_tag.cmdline, CmdLine); + + // move pointer to next tag + mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag); + } +} + +STATIC +VOID +SetupEndTag ( + VOID + ) +{ + // Empty tag ends list; this has zero length and no body + mLinuxKernelCurrentAtag->header.type = ATAG_NONE; + mLinuxKernelCurrentAtag->header.size = 0; + + /* We can not calculate the next address by using the standard macro: + * Params = next_tag_address(Params); + * because it relies on the header.size, which here it is 0 (zero). + * The easiest way is to add the sizeof(mLinuxKernelCurrentAtag->header). + */ + mLinuxKernelCurrentAtag = (LINUX_ATAG*)((UINT32)mLinuxKernelCurrentAtag + sizeof(mLinuxKernelCurrentAtag->header)); +} + +EFI_STATUS +PrepareAtagList ( + IN CONST CHAR8* CommandLineString, + IN EFI_PHYSICAL_ADDRESS InitrdImage, + IN UINTN InitrdImageSize, + OUT LINUX_ATAG **AtagBase, + OUT UINT32 *AtagSize + ) +{ + EFI_STATUS Status; + LIST_ENTRY *ResourceLink; + LIST_ENTRY ResourceList; + EFI_PHYSICAL_ADDRESS AtagStartAddress; + BDS_SYSTEM_MEMORY_RESOURCE *Resource; + + AtagStartAddress = LINUX_ATAG_MAX_OFFSET; + Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR,"Failed to allocate Atag at 0x%lX (%r)\n",AtagStartAddress,Status)); + Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress); + ASSERT_EFI_ERROR(Status); + } + + // Ready to setup the atag list + mLinuxKernelCurrentAtag = (LINUX_ATAG*)(UINTN)AtagStartAddress; + + // Standard core tag 4k PageSize + SetupCoreTag( (UINT32)SIZE_4KB ); + + // Physical memory setup + GetSystemMemoryResources (&ResourceList); + ResourceLink = ResourceList.ForwardLink; + while (ResourceLink != NULL && ResourceLink != &ResourceList) { + Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceLink; + DEBUG((EFI_D_INFO,"- [0x%08X,0x%08X]\n",(UINT32)Resource->PhysicalStart,(UINT32)Resource->PhysicalStart+(UINT32)Resource->ResourceLength)); + SetupMemTag( (UINT32)Resource->PhysicalStart, (UINT32)Resource->ResourceLength ); + ResourceLink = ResourceLink->ForwardLink; + } + + // CommandLine setting root device + if (CommandLineString) { + SetupCmdlineTag (CommandLineString); + } + + if (InitrdImageSize > 0 && InitrdImage != 0) { + mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_INITRD2); + mLinuxKernelCurrentAtag->header.type = ATAG_INITRD2; + + mLinuxKernelCurrentAtag->body.initrd2_tag.start = (UINT32)InitrdImage; + mLinuxKernelCurrentAtag->body.initrd2_tag.size = (UINT32)InitrdImageSize; + + // Move pointer to next tag + mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag); + } + + // End of tags + SetupEndTag(); + + // Calculate atag list size + *AtagBase = (LINUX_ATAG*)(UINTN)AtagStartAddress; + *AtagSize = (UINT32)mLinuxKernelCurrentAtag - (UINT32)AtagStartAddress + 1; + + return EFI_SUCCESS; +} + -- cgit v1.2.3