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
)) {
97 // Check the FDT header is valid. We only make this check in DEBUG mode in
98 // case the FDT header change on production device and this ASSERT() becomes
100 ASSERT (fdt_check_header ((VOID
*)(UINTN
)FdtBlobBase
) == 0);
103 // Ensure the Size of the Device Tree is smaller than the size of the read file
105 ASSERT ((UINTN
)fdt_totalsize ((VOID
*)(UINTN
)FdtBlobBase
) <= FdtBlobSize
);
108 // Store the FDT as Runtime Service Data to prevent the Kernel from
109 // overwritting its data.
111 NumPages
= EFI_SIZE_TO_PAGES (FdtBlobSize
);
112 Status
= gBS
->AllocatePages (
113 AllocateAnyPages
, EfiRuntimeServicesData
,
114 NumPages
, &FdtConfigurationTableBase
116 if (EFI_ERROR (Status
)) {
120 (VOID
*)(UINTN
)FdtConfigurationTableBase
,
121 (VOID
*)(UINTN
)FdtBlobBase
,
126 // Install the FDT into the Configuration Table
128 Status
= gBS
->InstallConfigurationTable (
130 (VOID
*)(UINTN
)FdtConfigurationTableBase
132 if (EFI_ERROR (Status
)) {
133 gBS
->FreePages (FdtConfigurationTableBase
, NumPages
);
137 if (FdtBlobBase
!= 0) {
138 gBS
->FreePages (FdtBlobBase
, NumPages
);
140 FreePool (DevicePath
);
146 Main entry point of the FDT platform driver.
148 @param[in] ImageHandle The firmware allocated handle for the present driver
150 @param[in] *SystemTable A pointer to the EFI System table.
152 @retval EFI_SUCCESS The driver was initialized.
153 @retval EFI_OUT_OF_RESOURCES The "End of DXE" event could not be allocated or
154 there was not enough memory in pool to install
155 the Shell Dynamic Command protocol.
156 @retval EFI_LOAD_ERROR Unable to add the HII package.
160 FdtPlatformEntryPoint (
161 IN EFI_HANDLE ImageHandle
,
162 IN EFI_SYSTEM_TABLE
*SystemTable
169 // Install the Device Tree from its expected location
171 Status
= RunFdtInstallation (NULL
);
172 if (EFI_ERROR (Status
)) {
176 if (FeaturePcdGet (PcdOverridePlatformFdt
) || FeaturePcdGet (PcdDumpFdtShellCommand
)) {
178 // Register the strings for the user interface in the HII Database.
179 // This shows the way to the multi-language support, even if
180 // only the English language is actually supported. The strings to register
181 // are stored in the "ShellSetFdtStrings[]" array. This array is
182 // built by the building process from the "*.uni" file associated to
183 // the present driver (cf. FdtPlatfromDxe.inf). Examine your Build
184 // folder under your package's DEBUG folder and you will find the array
185 // defined in a xxxStrDefs.h file.
187 mFdtPlatformDxeHiiHandle
= HiiAddPackages (
188 &mFdtPlatformDxeHiiGuid
,
190 FdtPlatformDxeStrings
,
196 // If the development features are enabled, install the dynamic shell
197 // command "setfdt" to be able to define a device path for the FDT
198 // that has precedence over the device paths defined by
199 // "PcdFdtDevicePaths".
202 if (FeaturePcdGet (PcdOverridePlatformFdt
)) {
203 if (mFdtPlatformDxeHiiHandle
!= NULL
) {
204 // We install dynamic EFI command on separate handles as we cannot register
205 // more than one protocol of the same protocol interface on the same handle.
207 Status
= gBS
->InstallMultipleProtocolInterfaces (
209 &gEfiShellDynamicCommandProtocolGuid
,
210 &mShellDynCmdProtocolSetFdt
,
213 if (EFI_ERROR (Status
)) {
214 HiiRemovePackages (mFdtPlatformDxeHiiHandle
);
217 Status
= EFI_LOAD_ERROR
;
219 if (EFI_ERROR (Status
)) {
222 "Unable to install \"setfdt\" EFI Shell command - %r \n",
228 if (FeaturePcdGet (PcdDumpFdtShellCommand
)) {
229 if (mFdtPlatformDxeHiiHandle
!= NULL
) {
230 // We install dynamic EFI command on separate handles as we cannot register
231 // more than one protocol of the same protocol interface on the same handle.
233 Status
= gBS
->InstallMultipleProtocolInterfaces (
235 &gEfiShellDynamicCommandProtocolGuid
,
236 &mShellDynCmdProtocolDumpFdt
,
239 if (EFI_ERROR (Status
)) {
240 HiiRemovePackages (mFdtPlatformDxeHiiHandle
);
243 Status
= EFI_LOAD_ERROR
;
245 if (EFI_ERROR (Status
)) {
248 "Unable to install \"dumpfdt\" EFI Shell command - %r \n",
258 Run the FDT installation process.
260 Loop in priority order over the device paths from which the FDT has
261 been asked to be retrieved for. For each device path, try to install
262 the FDT. Stop as soon as an installation succeeds.
264 @param[in] SuccessfullDevicePath If not NULL, address where to store the
265 pointer to the text device path from
266 which the FDT was successfully retrieved.
267 Not used if the FDT installation failed.
268 The returned address is the address of
269 an allocated buffer that has to be
272 @retval EFI_SUCCESS The FDT was installed.
273 @retval EFI_NOT_FOUND Failed to locate a protocol or a file.
274 @retval EFI_INVALID_PARAMETER Invalid device path.
275 @retval EFI_UNSUPPORTED Device path not supported.
276 @retval EFI_OUT_OF_RESOURCES An allocation failed.
281 OUT CHAR16
**SuccessfullDevicePath
286 CHAR16
*TextDevicePath
;
287 CHAR16
*TextDevicePathStart
;
288 CHAR16
*TextDevicePathSeparator
;
289 UINTN TextDevicePathLen
;
291 TextDevicePath
= NULL
;
293 // For development purpose, if enabled through the "PcdOverridePlatformFdt"
294 // feature PCD, try first to install the FDT specified by the device path in
295 // text form stored in the "Fdt" UEFI variable.
297 if (FeaturePcdGet (PcdOverridePlatformFdt
)) {
299 Status
= gRT
->GetVariable (
308 // Keep going only if the "Fdt" variable is defined.
311 if (Status
== EFI_BUFFER_TOO_SMALL
) {
312 TextDevicePath
= AllocatePool (DataSize
);
313 if (TextDevicePath
== NULL
) {
314 Status
= EFI_OUT_OF_RESOURCES
;
318 Status
= gRT
->GetVariable (
325 if (EFI_ERROR (Status
)) {
326 FreePool (TextDevicePath
);
330 Status
= InstallFdt (TextDevicePath
);
331 if (!EFI_ERROR (Status
)) {
334 "Installation of the FDT using the device path <%s> completed.\n",
341 "Installation of the FDT specified by the \"Fdt\" UEFI variable failed - %r\n",
344 FreePool (TextDevicePath
);
349 // Loop over the device path list provided by "PcdFdtDevicePaths". The device
350 // paths are in text form and separated by a semi-colon.
353 Status
= EFI_NOT_FOUND
;
354 for (TextDevicePathStart
= (CHAR16
*)PcdGetPtr (PcdFdtDevicePaths
);
355 *TextDevicePathStart
!= L
'\0' ; ) {
356 TextDevicePathSeparator
= StrStr (TextDevicePathStart
, L
";");
359 // Last device path of the list
361 if (TextDevicePathSeparator
== NULL
) {
362 TextDevicePathLen
= StrLen (TextDevicePathStart
);
364 TextDevicePathLen
= (UINTN
)(TextDevicePathSeparator
- TextDevicePathStart
);
367 TextDevicePath
= AllocateCopyPool (
368 (TextDevicePathLen
+ 1) * sizeof (CHAR16
),
371 if (TextDevicePath
== NULL
) {
372 Status
= EFI_OUT_OF_RESOURCES
;
375 TextDevicePath
[TextDevicePathLen
] = L
'\0';
377 Status
= InstallFdt (TextDevicePath
);
378 if (!EFI_ERROR (Status
)) {
379 DEBUG ((EFI_D_WARN
, "Installation of the FDT using the device path <%s> completed.\n",
385 DEBUG ((EFI_D_WARN
, "Installation of the FDT using the device path <%s> failed - %r.\n",
386 TextDevicePath
, Status
388 FreePool (TextDevicePath
);
390 if (TextDevicePathSeparator
== NULL
) {
393 TextDevicePathStart
= TextDevicePathSeparator
+ 1;
399 if (EFI_ERROR (Status
)) {
400 DEBUG ((EFI_D_ERROR
, "Failed to install the FDT - %r.\n", Status
));
404 if (SuccessfullDevicePath
!= NULL
) {
405 *SuccessfullDevicePath
= TextDevicePath
;
407 FreePool (TextDevicePath
);
414 Transcode one of the EFI return code used by the model into an EFI Shell return code.
416 @param[in] Status EFI return code.
418 @return Transcoded EFI Shell return code.
426 SHELL_STATUS ShellStatus
;
430 ShellStatus
= SHELL_SUCCESS
;
433 case EFI_INVALID_PARAMETER
:
434 ShellStatus
= SHELL_INVALID_PARAMETER
;
437 case EFI_UNSUPPORTED
:
438 ShellStatus
= SHELL_UNSUPPORTED
;
441 case EFI_DEVICE_ERROR
:
442 ShellStatus
= SHELL_DEVICE_ERROR
;
445 case EFI_WRITE_PROTECTED
:
446 case EFI_SECURITY_VIOLATION
:
447 ShellStatus
= SHELL_ACCESS_DENIED
;
450 case EFI_OUT_OF_RESOURCES
:
451 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
455 ShellStatus
= SHELL_NOT_FOUND
;
459 ShellStatus
= SHELL_ABORTED
;