/** @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 "LinuxInternal.h" #include #include /** The user Entry Point for Application. The user code starts with this function as the real entry point for the application. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI UefiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; LINUX_LOADER_OPTIONAL_DATA* LinuxOptionalData; EFI_DEVICE_PATH* DevicePathKernel; EFI_DEVICE_PATH* DevicePathFdt; EFI_DEVICE_PATH* InitrdDevicePath; CHAR16* OptionalDataInitrd; CHAR8* OptionalDataArguments; CHAR16* Initrd; Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage); ASSERT_EFI_ERROR (Status); if (LoadedImage->LoadOptionsSize == 0) { Status = LinuxLoaderConfig (LoadedImage); } else { // Ensure the signature is correct LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)LoadedImage->LoadOptions; if (LinuxOptionalData->Signature != LINUX_LOADER_SIGNATURE) { return EFI_UNSUPPORTED; } // Generate the File Path Node for the Linux Kernel & Device Tree blob DevicePathKernel = FileDevicePath (LoadedImage->DeviceHandle, LINUX_KERNEL_NAME); DevicePathFdt = FileDevicePath (LoadedImage->DeviceHandle, FDT_NAME); if (LinuxOptionalData->CmdLineLength > 0) { OptionalDataArguments = (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA); } else { OptionalDataArguments = NULL; } if (LinuxOptionalData->InitrdPathListLength > 0) { if (OptionalDataArguments != NULL) { OptionalDataInitrd = (CHAR16*)(OptionalDataArguments + LinuxOptionalData->CmdLineLength); } else { OptionalDataInitrd = (CHAR16*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA); } // If pointer not aligned if ((UINTN)OptionalDataInitrd & 0x1) { Initrd = (CHAR16*)AllocateCopyPool (LinuxOptionalData->InitrdPathListLength, OptionalDataInitrd); } else { Initrd = OptionalDataInitrd; } InitrdDevicePath = FileDevicePath (LoadedImage->DeviceHandle, Initrd); } else { OptionalDataInitrd = NULL; InitrdDevicePath = NULL; Initrd = NULL; } // Load and Start the Linux Kernel (we should never return) Status = BdsBootLinuxFdt (DevicePathKernel, InitrdDevicePath, OptionalDataArguments, DevicePathFdt); if ((UINTN)OptionalDataInitrd & 0x1) { FreePool (Initrd); } FreePool (DevicePathKernel); if (InitrdDevicePath) { FreePool (InitrdDevicePath); } } return Status; }