3 Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
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
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.
15 #include "FdtPlatform.h"
17 #include <Library/PcdLib.h>
18 #include <Library/DevicePathLib.h>
19 #include <Library/BdsLib.h>
21 #include <Protocol/DevicePath.h>
29 STATIC CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolSetFdt
= {
30 L
"setfdt", // Name of the command
31 ShellDynCmdSetFdtHandler
, // Handler
32 ShellDynCmdSetFdtGetHelp
// GetHelp
35 STATIC CONST EFI_GUID mFdtPlatformDxeHiiGuid
= {
36 0x8afa7610, 0x62b1, 0x46aa,
37 {0xb5, 0x34, 0xc3, 0xde, 0xff, 0x39, 0x77, 0x8c}
40 EFI_HANDLE mFdtPlatformDxeHiiHandle
;
43 Install the FDT specified by its device path in text form.
45 @param[in] TextDevicePath Device path of the FDT to install in text form
47 @retval EFI_SUCCESS The FDT was installed.
48 @retval EFI_NOT_FOUND Failed to locate a protocol or a file.
49 @retval EFI_INVALID_PARAMETER Invalid device path.
50 @retval EFI_UNSUPPORTED Device path not supported.
51 @retval EFI_OUT_OF_RESOURCES An allocation failed.
56 IN CONST CHAR16
* TextDevicePath
60 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*EfiDevicePathFromTextProtocol
;
61 EFI_DEVICE_PATH
*DevicePath
;
62 EFI_PHYSICAL_ADDRESS FdtBlobBase
;
65 EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase
;
67 Status
= gBS
->LocateProtocol (
68 &gEfiDevicePathFromTextProtocolGuid
,
70 (VOID
**)&EfiDevicePathFromTextProtocol
72 if (EFI_ERROR (Status
)) {
73 DEBUG ((EFI_D_ERROR
, "InstallFdt() - Failed to locate EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol\n"));
77 DevicePath
= (EFI_DEVICE_PATH
*)EfiDevicePathFromTextProtocol
->ConvertTextToDevicePath (TextDevicePath
);
78 if (DevicePath
== NULL
) {
79 return EFI_INVALID_PARAMETER
;
83 // Load the FDT given its device path.
84 // This operation may fail if the device path is not supported.
88 Status
= BdsLoadImage (DevicePath
, AllocateAnyPages
, &FdtBlobBase
, &FdtBlobSize
);
89 if (EFI_ERROR (Status
)) {
93 // Check the FDT header is valid. We only make this check in DEBUG mode in
94 // case the FDT header change on production device and this ASSERT() becomes
96 ASSERT (fdt_check_header ((VOID
*)(UINTN
)FdtBlobBase
) == 0);
99 // Ensure the Size of the Device Tree is smaller than the size of the read file
101 ASSERT ((UINTN
)fdt_totalsize ((VOID
*)(UINTN
)FdtBlobBase
) <= FdtBlobSize
);
104 // Store the FDT as Runtime Service Data to prevent the Kernel from
105 // overwritting its data.
107 NumPages
= EFI_SIZE_TO_PAGES (FdtBlobSize
);
108 Status
= gBS
->AllocatePages (
109 AllocateAnyPages
, EfiRuntimeServicesData
,
110 NumPages
, &FdtConfigurationTableBase
112 if (EFI_ERROR (Status
)) {
116 (VOID
*)(UINTN
)FdtConfigurationTableBase
,
117 (VOID
*)(UINTN
)FdtBlobBase
,
122 // Install the FDT into the Configuration Table
124 Status
= gBS
->InstallConfigurationTable (
126 (VOID
*)(UINTN
)FdtConfigurationTableBase
128 if (EFI_ERROR (Status
)) {
129 gBS
->FreePages (FdtConfigurationTableBase
, NumPages
);
133 if (FdtBlobBase
!= 0) {
134 gBS
->FreePages (FdtBlobBase
, NumPages
);
136 FreePool (DevicePath
);
142 Main entry point of the FDT platform driver.
144 @param[in] ImageHandle The firmware allocated handle for the present driver
146 @param[in] *SystemTable A pointer to the EFI System table.
148 @retval EFI_SUCCESS The driver was initialized.
149 @retval EFI_OUT_OF_RESOURCES The "End of DXE" event could not be allocated or
150 there was not enough memory in pool to install
151 the Shell Dynamic Command protocol.
152 @retval EFI_LOAD_ERROR Unable to add the HII package.
156 FdtPlatformEntryPoint (
157 IN EFI_HANDLE ImageHandle
,
158 IN EFI_SYSTEM_TABLE
*SystemTable
164 // Install the Device Tree from its expected location
166 Status
= RunFdtInstallation (NULL
);
167 if (EFI_ERROR (Status
)) {
172 // If the development features are enabled, install the dynamic shell
173 // command "setfdt" to be able to define a device path for the FDT
174 // that has precedence over the device paths defined by
175 // "PcdFdtDevicePaths".
178 if (FeaturePcdGet (PcdOverridePlatformFdt
)) {
180 // Register the strings for the user interface in the HII Database.
181 // This shows the way to the multi-language support, even if
182 // only the English language is actually supported. The strings to register
183 // are stored in the "ShellSetFdtStrings[]" array. This array is
184 // built by the building process from the "*.uni" file associated to
185 // the present driver (cf. FdtPlatfromDxe.inf). Examine your Build
186 // folder under your package's DEBUG folder and you will find the array
187 // defined in a xxxStrDefs.h file.
189 mFdtPlatformDxeHiiHandle
= HiiAddPackages (
190 &mFdtPlatformDxeHiiGuid
,
192 FdtPlatformDxeStrings
,
196 if (mFdtPlatformDxeHiiHandle
!= NULL
) {
197 Status
= gBS
->InstallMultipleProtocolInterfaces (
199 &gEfiShellDynamicCommandProtocolGuid
,
200 &mShellDynCmdProtocolSetFdt
,
203 if (EFI_ERROR (Status
)) {
204 HiiRemovePackages (mFdtPlatformDxeHiiHandle
);
207 Status
= EFI_LOAD_ERROR
;
209 if (EFI_ERROR (Status
)) {
212 "Unable to install \"setfdt\" EFI Shell command - %r \n",
222 Run the FDT installation process.
224 Loop in priority order over the device paths from which the FDT has
225 been asked to be retrieved for. For each device path, try to install
226 the FDT. Stop as soon as an installation succeeds.
228 @param[in] SuccessfullDevicePath If not NULL, address where to store the
229 pointer to the text device path from
230 which the FDT was successfully retrieved.
231 Not used if the FDT installation failed.
232 The returned address is the address of
233 an allocated buffer that has to be
236 @retval EFI_SUCCESS The FDT was installed.
237 @retval EFI_NOT_FOUND Failed to locate a protocol or a file.
238 @retval EFI_INVALID_PARAMETER Invalid device path.
239 @retval EFI_UNSUPPORTED Device path not supported.
240 @retval EFI_OUT_OF_RESOURCES An allocation failed.
245 OUT CHAR16
**SuccessfullDevicePath
250 CHAR16
*TextDevicePath
;
251 CHAR16
*TextDevicePathStart
;
252 CHAR16
*TextDevicePathSeparator
;
253 UINTN TextDevicePathLen
;
255 TextDevicePath
= NULL
;
257 // For development purpose, if enabled through the "PcdOverridePlatformFdt"
258 // feature PCD, try first to install the FDT specified by the device path in
259 // text form stored in the "Fdt" UEFI variable.
261 if (FeaturePcdGet (PcdOverridePlatformFdt
)) {
263 Status
= gRT
->GetVariable (
272 // Keep going only if the "Fdt" variable is defined.
275 if (Status
== EFI_BUFFER_TOO_SMALL
) {
276 TextDevicePath
= AllocatePool (DataSize
);
277 if (TextDevicePath
== NULL
) {
278 Status
= EFI_OUT_OF_RESOURCES
;
282 Status
= gRT
->GetVariable (
289 if (EFI_ERROR (Status
)) {
290 FreePool (TextDevicePath
);
294 Status
= InstallFdt (TextDevicePath
);
295 if (!EFI_ERROR (Status
)) {
298 "Installation of the FDT using the device path <%s> completed.\n",
305 "Installation of the FDT specified by the \"Fdt\" UEFI variable failed - %r\n",
308 FreePool (TextDevicePath
);
313 // Loop over the device path list provided by "PcdFdtDevicePaths". The device
314 // paths are in text form and separated by a semi-colon.
317 Status
= EFI_NOT_FOUND
;
318 for (TextDevicePathStart
= (CHAR16
*)PcdGetPtr (PcdFdtDevicePaths
);
319 *TextDevicePathStart
!= L
'\0' ; ) {
320 TextDevicePathSeparator
= StrStr (TextDevicePathStart
, L
";");
323 // Last device path of the list
325 if (TextDevicePathSeparator
== NULL
) {
326 TextDevicePathLen
= StrLen (TextDevicePathStart
);
328 TextDevicePathLen
= (UINTN
)(TextDevicePathSeparator
- TextDevicePathStart
);
331 TextDevicePath
= AllocateCopyPool (
332 (TextDevicePathLen
+ 1) * sizeof (CHAR16
),
335 if (TextDevicePath
== NULL
) {
336 Status
= EFI_OUT_OF_RESOURCES
;
339 TextDevicePath
[TextDevicePathLen
] = L
'\0';
341 Status
= InstallFdt (TextDevicePath
);
342 if (!EFI_ERROR (Status
)) {
343 DEBUG ((EFI_D_WARN
, "Installation of the FDT using the device path <%s> completed.\n",
349 DEBUG ((EFI_D_WARN
, "Installation of the FDT using the device path <%s> failed - %r.\n",
350 TextDevicePath
, Status
352 FreePool (TextDevicePath
);
354 if (TextDevicePathSeparator
== NULL
) {
357 TextDevicePathStart
= TextDevicePathSeparator
+ 1;
363 if (EFI_ERROR (Status
)) {
364 DEBUG ((EFI_D_ERROR
, "Failed to install the FDT - %r.\n", Status
));
368 if (SuccessfullDevicePath
!= NULL
) {
369 *SuccessfullDevicePath
= TextDevicePath
;
371 FreePool (TextDevicePath
);
378 Transcode one of the EFI return code used by the model into an EFI Shell return code.
380 @param[in] Status EFI return code.
382 @return Transcoded EFI Shell return code.
390 SHELL_STATUS ShellStatus
;
394 ShellStatus
= SHELL_SUCCESS
;
397 case EFI_INVALID_PARAMETER
:
398 ShellStatus
= SHELL_INVALID_PARAMETER
;
401 case EFI_UNSUPPORTED
:
402 ShellStatus
= SHELL_UNSUPPORTED
;
405 case EFI_DEVICE_ERROR
:
406 ShellStatus
= SHELL_DEVICE_ERROR
;
409 case EFI_WRITE_PROTECTED
:
410 case EFI_SECURITY_VIOLATION
:
411 ShellStatus
= SHELL_ACCESS_DENIED
;
414 case EFI_OUT_OF_RESOURCES
:
415 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
419 ShellStatus
= SHELL_NOT_FOUND
;
423 ShellStatus
= SHELL_ABORTED
;