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>
27 STATIC CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolSetFdt
= {
28 L
"setfdt", // Name of the command
29 ShellDynCmdSetFdtHandler
, // Handler
30 ShellDynCmdSetFdtGetHelp
// GetHelp
33 STATIC CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolDumpFdt
= {
34 L
"dumpfdt", // Name of the command
35 ShellDynCmdDumpFdtHandler
, // Handler
36 ShellDynCmdDumpFdtGetHelp
// GetHelp
39 STATIC CONST EFI_GUID mFdtPlatformDxeHiiGuid
= {
40 0x8afa7610, 0x62b1, 0x46aa,
41 {0xb5, 0x34, 0xc3, 0xde, 0xff, 0x39, 0x77, 0x8c}
44 EFI_HANDLE mFdtPlatformDxeHiiHandle
;
47 Install the FDT specified by its device path in text form.
49 @param[in] TextDevicePath Device path of the FDT to install in text form
51 @retval EFI_SUCCESS The FDT was installed.
52 @retval EFI_NOT_FOUND Failed to locate a protocol or a file.
53 @retval EFI_INVALID_PARAMETER Invalid device path.
54 @retval EFI_UNSUPPORTED Device path not supported.
55 @retval EFI_OUT_OF_RESOURCES An allocation failed.
60 IN CONST CHAR16
* TextDevicePath
64 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*EfiDevicePathFromTextProtocol
;
65 EFI_DEVICE_PATH
*DevicePath
;
66 EFI_PHYSICAL_ADDRESS FdtBlobBase
;
69 EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase
;
71 Status
= gBS
->LocateProtocol (
72 &gEfiDevicePathFromTextProtocolGuid
,
74 (VOID
**)&EfiDevicePathFromTextProtocol
76 if (EFI_ERROR (Status
)) {
77 DEBUG ((EFI_D_ERROR
, "InstallFdt() - Failed to locate EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol\n"));
81 DevicePath
= (EFI_DEVICE_PATH
*)EfiDevicePathFromTextProtocol
->ConvertTextToDevicePath (TextDevicePath
);
82 if (DevicePath
== NULL
) {
83 return EFI_INVALID_PARAMETER
;
87 // Load the FDT given its device path.
88 // This operation may fail if the device path is not supported.
92 Status
= BdsLoadImage (DevicePath
, AllocateAnyPages
, &FdtBlobBase
, &FdtBlobSize
);
93 if (EFI_ERROR (Status
)) {
98 // Ensure that the FDT header is valid and that the Size of the Device Tree
99 // is smaller than the size of the read file
101 if (fdt_check_header ((VOID
*)(UINTN
)FdtBlobBase
) != 0 ||
102 (UINTN
)fdt_totalsize ((VOID
*)(UINTN
)FdtBlobBase
) > FdtBlobSize
) {
103 DEBUG ((EFI_D_ERROR
, "InstallFdt() - loaded FDT binary image seems corrupt\n"));
104 Status
= EFI_LOAD_ERROR
;
109 // Store the FDT as Runtime Service Data to prevent the Kernel from
110 // overwritting its data.
112 NumPages
= EFI_SIZE_TO_PAGES (FdtBlobSize
);
113 Status
= gBS
->AllocatePages (
114 AllocateAnyPages
, EfiRuntimeServicesData
,
115 NumPages
, &FdtConfigurationTableBase
117 if (EFI_ERROR (Status
)) {
121 (VOID
*)(UINTN
)FdtConfigurationTableBase
,
122 (VOID
*)(UINTN
)FdtBlobBase
,
127 // Install the FDT into the Configuration Table
129 Status
= gBS
->InstallConfigurationTable (
131 (VOID
*)(UINTN
)FdtConfigurationTableBase
133 if (EFI_ERROR (Status
)) {
134 gBS
->FreePages (FdtConfigurationTableBase
, NumPages
);
138 if (FdtBlobBase
!= 0) {
139 gBS
->FreePages (FdtBlobBase
, NumPages
);
141 FreePool (DevicePath
);
147 Main entry point of the FDT platform driver.
149 @param[in] ImageHandle The firmware allocated handle for the present driver
151 @param[in] *SystemTable A pointer to the EFI System table.
153 @retval EFI_SUCCESS The driver was initialized.
154 @retval EFI_OUT_OF_RESOURCES The "End of DXE" event could not be allocated or
155 there was not enough memory in pool to install
156 the Shell Dynamic Command protocol.
157 @retval EFI_LOAD_ERROR Unable to add the HII package.
161 FdtPlatformEntryPoint (
162 IN EFI_HANDLE ImageHandle
,
163 IN EFI_SYSTEM_TABLE
*SystemTable
170 // Install the Device Tree from its expected location
172 Status
= RunFdtInstallation (NULL
);
173 if (EFI_ERROR (Status
)) {
177 if (FeaturePcdGet (PcdOverridePlatformFdt
) || FeaturePcdGet (PcdDumpFdtShellCommand
)) {
179 // Register the strings for the user interface in the HII Database.
180 // This shows the way to the multi-language support, even if
181 // only the English language is actually supported. The strings to register
182 // are stored in the "ShellSetFdtStrings[]" array. This array is
183 // built by the building process from the "*.uni" file associated to
184 // the present driver (cf. FdtPlatfromDxe.inf). Examine your Build
185 // folder under your package's DEBUG folder and you will find the array
186 // defined in a xxxStrDefs.h file.
188 mFdtPlatformDxeHiiHandle
= HiiAddPackages (
189 &mFdtPlatformDxeHiiGuid
,
191 FdtPlatformDxeStrings
,
197 // If the development features are enabled, install the dynamic shell
198 // command "setfdt" to be able to define a device path for the FDT
199 // that has precedence over the device paths defined by
200 // "PcdFdtDevicePaths".
203 if (FeaturePcdGet (PcdOverridePlatformFdt
)) {
204 if (mFdtPlatformDxeHiiHandle
!= NULL
) {
205 // We install dynamic EFI command on separate handles as we cannot register
206 // more than one protocol of the same protocol interface on the same handle.
208 Status
= gBS
->InstallMultipleProtocolInterfaces (
210 &gEfiShellDynamicCommandProtocolGuid
,
211 &mShellDynCmdProtocolSetFdt
,
214 if (EFI_ERROR (Status
)) {
215 HiiRemovePackages (mFdtPlatformDxeHiiHandle
);
218 Status
= EFI_LOAD_ERROR
;
220 if (EFI_ERROR (Status
)) {
223 "Unable to install \"setfdt\" EFI Shell command - %r \n",
229 if (FeaturePcdGet (PcdDumpFdtShellCommand
)) {
230 if (mFdtPlatformDxeHiiHandle
!= NULL
) {
231 // We install dynamic EFI command on separate handles as we cannot register
232 // more than one protocol of the same protocol interface on the same handle.
234 Status
= gBS
->InstallMultipleProtocolInterfaces (
236 &gEfiShellDynamicCommandProtocolGuid
,
237 &mShellDynCmdProtocolDumpFdt
,
240 if (EFI_ERROR (Status
)) {
241 HiiRemovePackages (mFdtPlatformDxeHiiHandle
);
244 Status
= EFI_LOAD_ERROR
;
246 if (EFI_ERROR (Status
)) {
249 "Unable to install \"dumpfdt\" EFI Shell command - %r \n",
259 Run the FDT installation process.
261 Loop in priority order over the device paths from which the FDT has
262 been asked to be retrieved for. For each device path, try to install
263 the FDT. Stop as soon as an installation succeeds.
265 @param[in] SuccessfullDevicePath If not NULL, address where to store the
266 pointer to the text device path from
267 which the FDT was successfully retrieved.
268 Not used if the FDT installation failed.
269 The returned address is the address of
270 an allocated buffer that has to be
273 @retval EFI_SUCCESS The FDT was installed.
274 @retval EFI_NOT_FOUND Failed to locate a protocol or a file.
275 @retval EFI_INVALID_PARAMETER Invalid device path.
276 @retval EFI_UNSUPPORTED Device path not supported.
277 @retval EFI_OUT_OF_RESOURCES An allocation failed.
282 OUT CHAR16
**SuccessfullDevicePath
287 CHAR16
*TextDevicePath
;
288 CHAR16
*TextDevicePathStart
;
289 CHAR16
*TextDevicePathSeparator
;
290 UINTN TextDevicePathLen
;
292 TextDevicePath
= NULL
;
294 // For development purpose, if enabled through the "PcdOverridePlatformFdt"
295 // feature PCD, try first to install the FDT specified by the device path in
296 // text form stored in the "Fdt" UEFI variable.
298 if (FeaturePcdGet (PcdOverridePlatformFdt
)) {
300 Status
= gRT
->GetVariable (
309 // Keep going only if the "Fdt" variable is defined.
312 if (Status
== EFI_BUFFER_TOO_SMALL
) {
313 TextDevicePath
= AllocatePool (DataSize
);
314 if (TextDevicePath
== NULL
) {
315 Status
= EFI_OUT_OF_RESOURCES
;
319 Status
= gRT
->GetVariable (
326 if (EFI_ERROR (Status
)) {
327 FreePool (TextDevicePath
);
331 Status
= InstallFdt (TextDevicePath
);
332 if (!EFI_ERROR (Status
)) {
335 "Installation of the FDT using the device path <%s> completed.\n",
342 "Installation of the FDT specified by the \"Fdt\" UEFI variable failed - %r\n",
345 FreePool (TextDevicePath
);
350 // Loop over the device path list provided by "PcdFdtDevicePaths". The device
351 // paths are in text form and separated by a semi-colon.
354 Status
= EFI_NOT_FOUND
;
355 for (TextDevicePathStart
= (CHAR16
*)PcdGetPtr (PcdFdtDevicePaths
);
356 *TextDevicePathStart
!= L
'\0' ; ) {
357 TextDevicePathSeparator
= StrStr (TextDevicePathStart
, L
";");
360 // Last device path of the list
362 if (TextDevicePathSeparator
== NULL
) {
363 TextDevicePathLen
= StrLen (TextDevicePathStart
);
365 TextDevicePathLen
= (UINTN
)(TextDevicePathSeparator
- TextDevicePathStart
);
368 TextDevicePath
= AllocateCopyPool (
369 (TextDevicePathLen
+ 1) * sizeof (CHAR16
),
372 if (TextDevicePath
== NULL
) {
373 Status
= EFI_OUT_OF_RESOURCES
;
376 TextDevicePath
[TextDevicePathLen
] = L
'\0';
378 Status
= InstallFdt (TextDevicePath
);
379 if (!EFI_ERROR (Status
)) {
380 DEBUG ((EFI_D_WARN
, "Installation of the FDT using the device path <%s> completed.\n",
386 DEBUG ((EFI_D_WARN
, "Installation of the FDT using the device path <%s> failed - %r.\n",
387 TextDevicePath
, Status
389 FreePool (TextDevicePath
);
391 if (TextDevicePathSeparator
== NULL
) {
394 TextDevicePathStart
= TextDevicePathSeparator
+ 1;
400 if (EFI_ERROR (Status
)) {
401 DEBUG ((EFI_D_ERROR
, "Failed to install the FDT - %r.\n", Status
));
405 if (SuccessfullDevicePath
!= NULL
) {
406 *SuccessfullDevicePath
= TextDevicePath
;
408 FreePool (TextDevicePath
);
415 Transcode one of the EFI return code used by the model into an EFI Shell return code.
417 @param[in] Status EFI return code.
419 @return Transcoded EFI Shell return code.
427 SHELL_STATUS ShellStatus
;
431 ShellStatus
= SHELL_SUCCESS
;
434 case EFI_INVALID_PARAMETER
:
435 ShellStatus
= SHELL_INVALID_PARAMETER
;
438 case EFI_UNSUPPORTED
:
439 ShellStatus
= SHELL_UNSUPPORTED
;
442 case EFI_DEVICE_ERROR
:
443 ShellStatus
= SHELL_DEVICE_ERROR
;
446 case EFI_WRITE_PROTECTED
:
447 case EFI_SECURITY_VIOLATION
:
448 ShellStatus
= SHELL_ACCESS_DENIED
;
451 case EFI_OUT_OF_RESOURCES
:
452 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
456 ShellStatus
= SHELL_NOT_FOUND
;
460 ShellStatus
= SHELL_ABORTED
;