3 * Copyright (c) 2014, ARM Limited. All rights reserved.
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.
16 #include <Library/DebugLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
20 #include <Protocol/DevicePath.h>
21 #include <Protocol/SimpleFileSystem.h>
24 #include <Guid/FileInfo.h>
29 // Device path for SemiHosting
32 VENDOR_DEVICE_PATH Guid
;
33 EFI_DEVICE_PATH_PROTOCOL End
;
34 } mSemihostingDevicePath
= {
36 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, { sizeof (VENDOR_DEVICE_PATH
), 0 } },
37 { 0xC5B9C74A, 0x6D72, 0x4719, { 0x99, 0xAB, 0xC5, 0x9F, 0x19, 0x90, 0x91, 0xEB } }
39 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0 } }
44 This function declares the passed FDT into the UEFI Configuration Table
46 @param FdtBlob Base address of the Fdt Blob in System Memory
47 @param FdtSize Size of the Fdt Blob in System Memory
49 @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table
50 @return !EFI_SUCCESS Error returned by BS.InstallConfigurationTable()
55 InstallFdtIntoConfigurationTable (
62 // Check the FDT header is valid. We only make this check in DEBUG mode in case the FDT header change on
63 // production device and this ASSERT() becomes not valid.
64 ASSERT (fdt_check_header (FdtBlob
) == 0);
66 // Ensure the Size of the Device Tree is smaller than the size of the read file
67 ASSERT ((UINTN
)fdt_totalsize (FdtBlob
) <= FdtSize
);
69 // Install the FDT into the Configuration Table
70 Status
= gBS
->InstallConfigurationTable (&gFdtTableGuid
, FdtBlob
);
77 Load and Install FDT from Semihosting
79 @param Filename Name of the file to load from semihosting
81 @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table
83 @return EFI_NOT_FOUND Fail to locate the file in semihosting
84 @return EFI_OUT_OF_RESOURCES Fail to allocate memory to contain the blob
87 InstallFdtFromSemihosting (
88 IN CONST CHAR16
* FileName
92 EFI_DEVICE_PATH
* Remaining
;
94 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SemihostingFs
;
95 EFI_FILE_PROTOCOL
*Fs
;
96 EFI_FILE_PROTOCOL
*File
;
97 EFI_PHYSICAL_ADDRESS FdtBase
;
98 EFI_FILE_INFO
*FileInfo
;
102 // Ensure the Semihosting driver is initialized
103 Remaining
= (EFI_DEVICE_PATH
*)&mSemihostingDevicePath
;
104 // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns
105 // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified
106 // to point to the remaining part of the device path
107 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &Remaining
, &Handle
);
108 if (EFI_ERROR (Status
)) {
109 ASSERT_EFI_ERROR (Status
);
113 // Recursive = FALSE: We do not want to start the whole device tree
114 Status
= gBS
->ConnectController (Handle
, NULL
, Remaining
, FALSE
);
115 if (EFI_ERROR (Status
)) {
119 // Locate the FileSystem
120 Status
= gBS
->HandleProtocol (Handle
, &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&SemihostingFs
);
121 if (EFI_ERROR (Status
)) {
122 ASSERT_EFI_ERROR (Status
);
126 // Try to Open the volume and get root directory
127 Status
= SemihostingFs
->OpenVolume (SemihostingFs
, &Fs
);
128 if (EFI_ERROR (Status
)) {
129 DEBUG ((EFI_D_WARN
, "Warning: Fail to open semihosting filesystem that should contain FDT file.\n"));
134 Status
= Fs
->Open (Fs
, &File
, (CHAR16
*)FileName
, EFI_FILE_MODE_READ
, 0);
135 if (EFI_ERROR (Status
)) {
136 DEBUG ((EFI_D_WARN
, "Warning: Fail to load FDT file '%s'.\n", FileName
));
142 File
->GetInfo (File
, &gEfiFileInfoGuid
, &FileInfoSize
, NULL
);
143 FileInfo
= AllocatePool (FileInfoSize
);
144 if (FileInfo
== NULL
) {
145 Status
= EFI_OUT_OF_RESOURCES
;
148 Status
= File
->GetInfo (File
, &gEfiFileInfoGuid
, &FileInfoSize
, FileInfo
);
149 if (EFI_ERROR (Status
)) {
155 FdtSize
= FileInfo
->FileSize
;
158 // The FDT blob is attached to the Configuration Table. It is recommended to load it as Runtime Service Data
159 // to prevent the kernel to overwrite its data
160 Status
= gBS
->AllocatePages (AllocateAnyPages
, EfiRuntimeServicesData
, EFI_SIZE_TO_PAGES (FdtSize
), &FdtBase
);
161 if (!EFI_ERROR (Status
)) {
162 Status
= File
->Read (File
, &FdtSize
, (VOID
*)(UINTN
)(FdtBase
));
163 if (EFI_ERROR (Status
)) {
164 gBS
->FreePages (FdtBase
, EFI_SIZE_TO_PAGES (FdtSize
));
166 // Install the FDT as part of the UEFI Configuration Table
167 Status
= InstallFdtIntoConfigurationTable ((VOID
*)(UINTN
)FdtBase
, FdtSize
);
168 if (EFI_ERROR (Status
)) {
169 gBS
->FreePages (FdtBase
, EFI_SIZE_TO_PAGES (FdtSize
));