]>
Commit | Line | Data |
---|---|---|
1bfda055 | 1 | /** @file |
2 | * | |
3 | * Copyright (c) 2011, ARM Limited. All rights reserved. | |
4 | * | |
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 | |
9 | * | |
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. | |
12 | * | |
13 | **/ | |
14 | ||
15 | #include "BdsInternal.h" | |
16 | ||
17 | // Count the number of DevicePath Node | |
18 | static UINTN NumberNodeFromDevicePath( | |
19 | IN EFI_DEVICE_PATH_PROTOCOL* DevicePath | |
20 | ) { | |
21 | UINTN NumberDevicePathNode = 0; | |
22 | ||
23 | while (!IsDevicePathEnd (DevicePath)) { | |
24 | NumberDevicePathNode++; | |
25 | DevicePath = NextDevicePathNode(DevicePath); | |
26 | } | |
27 | return NumberDevicePathNode; | |
28 | } | |
29 | ||
30 | // Extract the FilePath from the Device Path | |
31 | CHAR16* BdsExtractFilePathFromDevicePath( | |
32 | IN CONST CHAR16 *StrDevicePath, | |
33 | IN UINTN NumberDevicePathNode | |
34 | ) { | |
35 | UINTN Node; | |
36 | CHAR16 *Str; | |
37 | ||
38 | Str = (CHAR16*)StrDevicePath; | |
39 | Node = 0; | |
40 | while ((Str != NULL) && (*Str != L'\0') && (Node < NumberDevicePathNode)) { | |
41 | if ((*Str == L'/') || (*Str == L'\\')) { | |
42 | Node++; | |
43 | } | |
44 | Str++; | |
45 | } | |
46 | ||
47 | if (*Str == L'\0') { | |
48 | return NULL; | |
49 | } else { | |
50 | return Str; | |
51 | } | |
52 | } | |
53 | ||
54 | EFI_STATUS | |
55 | BdsLoadDevicePath( | |
56 | IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, | |
57 | OUT EFI_HANDLE *Handle | |
58 | ) { | |
59 | EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; | |
60 | EFI_STATUS Status; | |
61 | ||
62 | if ((DevicePath == NULL) || (Handle == NULL)) { | |
63 | return EFI_INVALID_PARAMETER; | |
64 | } | |
65 | ||
66 | do { | |
67 | RemainingDevicePath = DevicePath; | |
68 | // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns | |
69 | // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified | |
70 | // to point to the remaining part of the device path | |
71 | Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle); | |
72 | if (!EFI_ERROR (Status)) { | |
73 | // Recursive = FALSE: We do not want to start all the device tree | |
74 | Status = gBS->ConnectController (*Handle, NULL, RemainingDevicePath, FALSE); | |
75 | } | |
76 | ||
77 | // We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling | |
78 | // NextDevicePathNode() will return an undetermined Device Path Node | |
79 | if (!IsDevicePathEnd (RemainingDevicePath)) { | |
80 | RemainingDevicePath = NextDevicePathNode (RemainingDevicePath); | |
81 | } | |
82 | } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath)); | |
83 | ||
84 | if (!EFI_ERROR (Status)) { | |
85 | // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver | |
86 | // Binding Protocol are connected (such as DiskIo and SimpleFileSystem) | |
87 | RemainingDevicePath = DevicePath; | |
88 | Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle); | |
89 | if (!EFI_ERROR (Status)) { | |
90 | Status = gBS->ConnectController (*Handle, NULL, RemainingDevicePath, FALSE); | |
91 | if (EFI_ERROR (Status)) { | |
92 | // If the last node is a Memory Map Device Path just return EFI_SUCCESS. | |
93 | if ((RemainingDevicePath->Type == HARDWARE_DEVICE_PATH) && (RemainingDevicePath->SubType == HW_MEMMAP_DP)) { | |
94 | Status = EFI_SUCCESS; | |
95 | } | |
96 | } | |
97 | } | |
98 | } else if (IsDevicePathEnd (RemainingDevicePath)) { | |
99 | // Case when the DevicePath contains a MemoryMap Device Path Node and all drivers are connected. | |
100 | // Ensure the Device Path exists | |
101 | RemainingDevicePath = DevicePath; | |
102 | Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle); | |
103 | } | |
104 | ||
105 | return Status; | |
106 | } | |
107 | ||
108 | ||
109 | EFI_STATUS | |
110 | BdsLoadFilePath ( | |
111 | IN CONST CHAR16 *DeviceFilePath, | |
112 | OUT BDS_FILE *File | |
113 | ) { | |
114 | EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
115 | EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; | |
116 | EFI_STATUS Status; | |
117 | EFI_HANDLE Handle; | |
118 | UINTN NumberDevicePathNode; | |
119 | CHAR16 *FilePath; | |
120 | ||
121 | //Do a sanity check on the Device file path | |
122 | if (DeviceFilePath == NULL) { | |
123 | return EFI_INVALID_PARAMETER; | |
124 | } | |
125 | ||
126 | // Convert the Device Path String into Device Path Protocol | |
127 | Status = gBS->LocateProtocol(&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); | |
128 | ASSERT_EFI_ERROR(Status); | |
129 | DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath(DeviceFilePath); | |
130 | ||
131 | //Do a sanity check on the Device Path | |
132 | if (DevicePath == NULL) { | |
133 | return EFI_INVALID_PARAMETER; | |
134 | } | |
135 | ||
136 | // Count the number of DevicePath Node | |
137 | NumberDevicePathNode = NumberNodeFromDevicePath(DevicePath); | |
138 | // Extract the FilePath from the Device Path | |
139 | FilePath = BdsExtractFilePathFromDevicePath(DeviceFilePath,NumberDevicePathNode); | |
140 | ||
141 | Status = BdsLoadDevicePath(DevicePath,&Handle); | |
142 | if (EFI_ERROR (Status)) { | |
143 | return Status; | |
144 | } | |
145 | ||
146 | //If FilePath == NULL then let consider if a MemoryMap Device Path | |
147 | if (FilePath == NULL) { | |
148 | // Check if the Node is a MemoryMap Device Path | |
149 | Status = BdsLoadFileFromMemMap(Handle,DevicePath,File); | |
150 | } else { | |
151 | Status = BdsLoadFileFromSimpleFileSystem(Handle,FilePath,File); | |
152 | if (EFI_ERROR (Status)) { | |
153 | Status = BdsLoadFileFromFirmwareVolume(Handle,FilePath,EFI_FV_FILETYPE_ALL,File); | |
154 | } | |
155 | } | |
156 | ||
157 | if (!EFI_ERROR (Status)) { | |
158 | File->DevicePath = DevicePath; | |
159 | } | |
160 | ||
161 | return Status; | |
162 | } | |
163 | ||
164 | EFI_STATUS BdsCopyRawFileToRuntimeMemory( | |
165 | IN BDS_FILE *File, | |
166 | OUT VOID **FileImage, | |
167 | OUT UINTN *FileSize | |
168 | ) { | |
169 | if (File == NULL) { | |
170 | return EFI_INVALID_PARAMETER; | |
171 | } | |
172 | ||
173 | if (File->Type == BDS_FILETYPE_FS) { | |
174 | return BdsCopyRawFileToRuntimeMemoryFS(File->File.Fs.Handle,FileImage,FileSize); | |
175 | } else if (File->Type == BDS_FILETYPE_FV) { | |
176 | return BdsCopyRawFileToRuntimeMemoryFV(&(File->File.Fv),FileImage,FileSize); | |
177 | } else if (File->Type == BDS_FILETYPE_MEM) { | |
178 | return BdsCopyRawFileToRuntimeMemoryMemMap(&(File->File.Mem),FileImage,FileSize); | |
179 | } else { | |
180 | return EFI_INVALID_PARAMETER; | |
181 | } | |
182 | } |