Home | History | Annotate | Download | only in LinuxLoader
      1 /** @file
      2 *
      3 *  Copyright (c) 2011-2015, ARM Limited. All rights reserved.
      4 *
      5 *  This program and the accompanying materials
      6 *  are licensed and made available under the terms and conditions of the BSD License
      7 *  which accompanies this distribution.  The full text of the license may be found at
      8 *  http://opensource.org/licenses/bsd-license.php
      9 *
     10 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 *
     13 **/
     14 
     15 #include <Library/UefiApplicationEntryPoint.h>
     16 #include <Library/BaseMemoryLib.h>
     17 
     18 #include <Protocol/DevicePathFromText.h>
     19 
     20 #include "LinuxLoader.h"
     21 
     22 /**
     23   The user Entry Point for Application. The user code starts with this function
     24   as the real entry point for the application.
     25 
     26   @param[in]  ImageHandle  The firmware allocated handle for the EFI image.
     27   @param[in]  SystemTable  A pointer to the EFI System Table.
     28 
     29   @retval  EFI_SUCCESS            The entry point was executed successfully.
     30   @retval  EFI_NOT_FOUND          Protocol not found.
     31   @retval  EFI_NOT_FOUND          Path to the Linux kernel not found.
     32   @retval  EFI_ABORTED            The initialisation of the Shell Library failed.
     33   @retval  EFI_INVALID_PARAMETER  At least one parameter is not valid or there is a
     34                                   conflict between two parameters.
     35   @retval  EFI_OUT_OF_RESOURCES   A memory allocation failed.
     36 
     37 **/
     38 EFI_STATUS
     39 EFIAPI
     40 LinuxLoaderEntryPoint (
     41   IN EFI_HANDLE        ImageHandle,
     42   IN EFI_SYSTEM_TABLE  *SystemTable
     43   )
     44 {
     45   EFI_STATUS                          Status;
     46   EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL  *EfiDevicePathFromTextProtocol;
     47   EFI_SHELL_PARAMETERS_PROTOCOL       *ShellParameters;
     48   CHAR16                              *KernelPath;
     49   CHAR16                              *FdtPath;
     50   CHAR16                              *InitrdPath;
     51   CHAR16                              *KernelTextDevicePath;
     52   CHAR16                              *FdtTextDevicePath;
     53   CHAR16                              *InitrdTextDevicePath;
     54   CHAR16                              *LinuxCommandLine;
     55   UINTN                               AtagMachineType;
     56   EFI_DEVICE_PATH                     *KernelDevicePath;
     57   EFI_DEVICE_PATH                     *FdtDevicePath;
     58   EFI_DEVICE_PATH                     *InitrdDevicePath;
     59   CHAR8                               *AsciiLinuxCommandLine;
     60   LIST_ENTRY                          ResourceList;
     61   LIST_ENTRY                          *ResourceLink;
     62   SYSTEM_MEMORY_RESOURCE              *Resource;
     63   EFI_PHYSICAL_ADDRESS                SystemMemoryBase;
     64 
     65   Status = gBS->LocateProtocol (
     66                   &gEfiDevicePathFromTextProtocolGuid,
     67                   NULL,
     68                   (VOID **)&EfiDevicePathFromTextProtocol
     69                   );
     70   if (EFI_ERROR (Status)) {
     71     return EFI_NOT_FOUND;
     72   }
     73 
     74   //
     75   // Register the strings for the user interface in the HII Database.
     76   // This shows the way to the multi-language support, even if
     77   // only the English language is actually supported. The strings to register
     78   // are stored in the "LinuxLoaderStrings[]" array. This array is
     79   // built by the building process from the "*.uni" file associated to
     80   // the present application (cf. LinuxLoader.inf). Examine the Build
     81   // folder of the application and you will find the array defined in the
     82   // LinuxLoaderStrDefs.h file.
     83   //
     84   mLinuxLoaderHiiHandle = HiiAddPackages (
     85                              &mLinuxLoaderHiiGuid,
     86                              ImageHandle,
     87                              LinuxLoaderStrings,
     88                              NULL
     89                              );
     90   if (mLinuxLoaderHiiHandle == NULL) {
     91     return EFI_NOT_FOUND;
     92   }
     93 
     94   Status = gBS->HandleProtocol (
     95                   ImageHandle,
     96                   &gEfiShellParametersProtocolGuid,
     97                   (VOID**)&ShellParameters
     98                   );
     99 
    100   KernelDevicePath      = NULL;
    101   FdtDevicePath         = NULL;
    102   InitrdDevicePath      = NULL;
    103   AsciiLinuxCommandLine = NULL;
    104 
    105   //
    106   // Call the proper function to handle the command line
    107   // depending on whether the application has been called
    108   // from the Shell or not.
    109   //
    110 
    111   if (!EFI_ERROR (Status)) {
    112     KernelTextDevicePath = NULL;
    113     FdtTextDevicePath    = NULL;
    114     InitrdTextDevicePath = NULL;
    115 
    116     Status = ProcessShellParameters (
    117                &KernelPath, &FdtPath, &InitrdPath, &LinuxCommandLine, &AtagMachineType
    118                );
    119     if (EFI_ERROR (Status)) {
    120       goto Error;
    121     }
    122 
    123     KernelDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (KernelPath);
    124     if (KernelDevicePath != NULL) {
    125       FreePool (KernelPath);
    126     } else {
    127       KernelTextDevicePath = KernelPath;
    128     }
    129 
    130     if (FdtPath != NULL) {
    131       FdtDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (FdtPath);
    132       if (FdtDevicePath != NULL) {
    133         FreePool (FdtPath);
    134       } else {
    135         FdtTextDevicePath = FdtPath;
    136       }
    137     }
    138 
    139     if (InitrdPath != NULL) {
    140       InitrdDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (InitrdPath);
    141       if (InitrdDevicePath != NULL) {
    142         FreePool (InitrdPath);
    143       } else {
    144         InitrdTextDevicePath = InitrdPath;
    145       }
    146     }
    147 
    148   } else {
    149     Status = ProcessAppCommandLine (
    150                &KernelTextDevicePath, &FdtTextDevicePath,
    151                &InitrdTextDevicePath, &LinuxCommandLine, &AtagMachineType
    152                );
    153     if (EFI_ERROR (Status)) {
    154       goto Error;
    155     }
    156   }
    157 
    158   Status = EFI_INVALID_PARAMETER;
    159   if (KernelTextDevicePath != NULL) {
    160     KernelDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (
    161                                                         KernelTextDevicePath
    162                                                         );
    163     if (KernelDevicePath == NULL) {
    164       goto Error;
    165     }
    166   }
    167   if (FdtTextDevicePath != NULL) {
    168     FdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (
    169                                                      FdtTextDevicePath
    170                                                      );
    171     if (FdtDevicePath == NULL) {
    172       goto Error;
    173     }
    174   }
    175   if (InitrdTextDevicePath != NULL) {
    176     InitrdDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (
    177                                                         InitrdTextDevicePath
    178                                                         );
    179     if (InitrdDevicePath == NULL) {
    180       goto Error;
    181     }
    182   }
    183 
    184   if (LinuxCommandLine != NULL) {
    185     AsciiLinuxCommandLine = AllocatePool ((StrLen (LinuxCommandLine) + 1) * sizeof (CHAR8));
    186     if (AsciiLinuxCommandLine == NULL) {
    187       Status = EFI_OUT_OF_RESOURCES;
    188       goto Error;
    189     }
    190     UnicodeStrToAsciiStr (LinuxCommandLine, AsciiLinuxCommandLine);
    191   }
    192 
    193   //
    194   // Find Base of System Memory - we keep the lowest physical address
    195   //
    196   SystemMemoryBase = ~0;
    197   GetSystemMemoryResources (&ResourceList);
    198   ResourceLink = ResourceList.ForwardLink;
    199   while (ResourceLink != NULL && ResourceLink != &ResourceList) {
    200     Resource = (SYSTEM_MEMORY_RESOURCE*)ResourceLink;
    201     if (Resource->PhysicalStart < SystemMemoryBase) {
    202       SystemMemoryBase = Resource->PhysicalStart;
    203     }
    204     ResourceLink = ResourceLink->ForwardLink;
    205   }
    206 
    207   if (AtagMachineType != ARM_FDT_MACHINE_TYPE) {
    208     Status = BootLinuxAtag (SystemMemoryBase, KernelDevicePath, InitrdDevicePath, AsciiLinuxCommandLine, AtagMachineType);
    209   } else {
    210     Status = BootLinuxFdt (SystemMemoryBase, KernelDevicePath, InitrdDevicePath, FdtDevicePath, AsciiLinuxCommandLine);
    211   }
    212 
    213 Error:
    214   if (KernelTextDevicePath != NULL) {
    215     FreePool (KernelTextDevicePath);
    216   }
    217   if (FdtTextDevicePath != NULL) {
    218     FreePool (FdtTextDevicePath);
    219   }
    220   if (InitrdTextDevicePath != NULL) {
    221     FreePool (InitrdTextDevicePath);
    222   }
    223   if (LinuxCommandLine != NULL) {
    224     FreePool (LinuxCommandLine);
    225   }
    226   if (KernelDevicePath != NULL) {
    227     FreePool (KernelDevicePath);
    228   }
    229   if (FdtDevicePath != NULL) {
    230     FreePool (FdtDevicePath);
    231   }
    232   if (InitrdDevicePath != NULL) {
    233     FreePool (InitrdDevicePath);
    234   }
    235   if (AsciiLinuxCommandLine != NULL) {
    236     FreePool (AsciiLinuxCommandLine);
    237   }
    238 
    239   if (EFI_ERROR (Status)) {
    240     PrintHii (NULL, STRING_TOKEN (STR_ERROR), Status);
    241   }
    242 
    243   HiiRemovePackages (mLinuxLoaderHiiHandle);
    244 
    245   return Status;
    246 }
    247