1 /** @file
2 *
3 * Copyright (c) 2014, ARM Ltd. All rights reserved.
4 *
5 * This program and the accompanying materials are licensed and made available
6 * under the terms and conditions of the BSD License which accompanies this
7 * 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, WITHOUT
11 * WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 *
13 **/
14
15 #include <Library/BaseLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/UefiLib.h>
20
21 #include <Guid/BootMonFsFileInfo.h>
22 #include <Protocol/SimpleFileSystem.h> // EFI_FILE_HANDLE
23
24 #include "ArmShellCmdRunAxf.h"
25 #include "BootMonFsLoader.h"
26
27 /**
28 Check that loading the file is supported.
29
30 Not all information is checked, only the properties that matters to us in
31 our simplified loader.
32
33 BootMonFS file properties is not in a file header but in the file-system
34 metadata, so we need to pass a handle to the file to allow access to the
35 information.
36
37 @param[in] FileHandle Handle of the file to check.
38
39 @retval EFI_SUCCESS on success.
40 @retval EFI_INVALID_PARAMETER if the header is invalid.
41 @retval EFI_UNSUPPORTED if the file type/platform is not supported.
42 **/
43 EFI_STATUS
BootMonFsCheckFile(IN CONST EFI_FILE_HANDLE FileHandle)44 BootMonFsCheckFile (
45 IN CONST EFI_FILE_HANDLE FileHandle
46 )
47 {
48 EFI_STATUS Status;
49 BOOTMON_FS_FILE_INFO Info;
50 UINTN InfoSize;
51 UINTN Index;
52
53 ASSERT (FileHandle != NULL);
54
55 // Try to load the file information as BootMonFS executable.
56 InfoSize = sizeof (Info);
57 // Get BootMon File info and see if it gives us what we need to load the file.
58 Status = FileHandle->GetInfo (FileHandle, &gArmBootMonFsFileInfoGuid,
59 &InfoSize, &Info);
60
61 if (!EFI_ERROR (Status)) {
62 // Check the values return to see if they look reasonable.
63 // Do we have a good entrypoint and at least one good load region?
64 // We assume here that we cannot load to address 0x0.
65 if ((Info.Size == 0) || (Info.EntryPoint == 0) || (Info.RegionCount == 0) ||
66 (Info.RegionCount > BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX)) {
67 // The file does not seem to be of the right type.
68 Status = EFI_UNSUPPORTED;
69 } else {
70 // Check load regions. We just check for valid numbers, we dont do the
71 // checksums. Info.Offset can be zero if it loads from the start of the
72 // file.
73 for (Index = 0; Index < Info.RegionCount; Index++) {
74 if ((Info.Region[Index].LoadAddress == 0) || (Info.Region[Index].Size == 0)) {
75 Status = EFI_UNSUPPORTED;
76 break;
77 }
78 }
79 }
80 }
81
82 return Status;
83 }
84
85 /**
86 Load a binary file from BootMonFS.
87
88 @param[in] FileHandle Handle of the file to load.
89
90 @param[in] FileData Address of the file data in memory.
91
92 @param[out] EntryPoint Will be filled with the ELF entry point address.
93
94 @param[out] ImageSize Will be filled with the file size in memory. This
95 will effectively be equal to the sum of the load
96 region sizes.
97
98 This function assumes the file is valid and supported as checked with
99 BootMonFsCheckFile().
100
101 @retval EFI_SUCCESS on success.
102 @retval EFI_INVALID_PARAMETER if the file is invalid.
103 **/
104 EFI_STATUS
BootMonFsLoadFile(IN CONST EFI_FILE_HANDLE FileHandle,IN CONST VOID * FileData,OUT VOID ** EntryPoint,OUT LIST_ENTRY * LoadList)105 BootMonFsLoadFile (
106 IN CONST EFI_FILE_HANDLE FileHandle,
107 IN CONST VOID *FileData,
108 OUT VOID **EntryPoint,
109 OUT LIST_ENTRY *LoadList
110 )
111 {
112 EFI_STATUS Status;
113 BOOTMON_FS_FILE_INFO Info;
114 UINTN InfoSize;
115 UINTN Index;
116 UINTN ImageSize;
117 RUNAXF_LOAD_LIST *LoadNode;
118
119 ASSERT (FileHandle != NULL);
120 ASSERT (FileData != NULL);
121 ASSERT (EntryPoint != NULL);
122 ASSERT (LoadList != NULL);
123
124 ImageSize = 0;
125
126 InfoSize = sizeof (Info);
127 Status = FileHandle->GetInfo (FileHandle, &gArmBootMonFsFileInfoGuid,
128 &InfoSize, &Info);
129
130 if (!EFI_ERROR (Status)) {
131 *EntryPoint = (VOID*)((UINTN)Info.EntryPoint);
132 // Load all the regions to run-time memory
133 for (Index = 0; Index < Info.RegionCount; Index++) {
134 LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
135 if (LoadNode == NULL) {
136 Status = EFI_OUT_OF_RESOURCES;
137 break;
138 }
139
140 LoadNode->MemOffset = (UINTN)Info.Region[Index].LoadAddress;
141 LoadNode->FileOffset = (UINTN)FileData + Info.Region[Index].Offset;
142 LoadNode->Length = (UINTN)Info.Region[Index].Size;
143 InsertTailList (LoadList, &LoadNode->Link);
144
145 ImageSize += LoadNode->Length;
146 }
147 }
148
149 if ((!EFI_ERROR (Status)) && (ImageSize == 0)) {
150 Status = EFI_INVALID_PARAMETER;
151 }
152
153 return Status;
154 }
155