- Implement BmpFwGetApplicationDirectoryPath and most of BmFwInitializeBootDirectoryPath.
[reactos.git] / reactos / boot / environ / lib / misc / bcd.c
1 /*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/misc/bcd.c
5 * PURPOSE: Boot Library BCD Routines
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "bl.h"
12
13 /* FUNCTIONS *****************************************************************/
14
15 PBL_BCD_OPTION
16 MiscGetBootOption (
17 _In_ PBL_BCD_OPTION List,
18 _In_ ULONG Type
19 )
20 {
21 ULONG_PTR NextOption = 0, ListOption;
22 PBL_BCD_OPTION Option;
23
24 /* No options, bail out */
25 if (!List)
26 {
27 return NULL;
28 }
29
30 /* Loop while we find an option */
31 while (TRUE)
32 {
33 /* Get the next option and see if it matches the type */
34 Option = (PBL_BCD_OPTION)((ULONG_PTR)List + NextOption);
35 if ((Option->Type == Type) && !(Option->Empty))
36 {
37 break;
38 }
39
40 /* Store the offset of the next option */
41 NextOption = Option->NextEntryOffset;
42
43 /* Failed to match. Check for list options */
44 ListOption = Option->ListOffset;
45 if (ListOption)
46 {
47 /* Try to get a match in the associated option */
48 Option = MiscGetBootOption((PBL_BCD_OPTION)((ULONG_PTR)Option +
49 ListOption),
50 Type);
51
52 /* Found one, return it */
53 if (Option)
54 {
55 return Option;
56 }
57 }
58 }
59
60 /* We found the option, return it */
61 return Option;
62 }
63
64 NTSTATUS
65 BlGetBootOptionString (
66 _In_ PBL_BCD_OPTION List,
67 _In_ ULONG Type,
68 _Out_ PWCHAR* Value
69 )
70 {
71 NTSTATUS Status;
72 PBL_BCD_OPTION Option;
73 PWCHAR String, StringCopy;
74 ULONG StringLength, CopyLength;
75 //PGUID AppIdentifier;
76
77 /* Make sure this is a BCD_STRING */
78 if ((Type & 0xF000000) != 0x2000000)
79 {
80 return STATUS_INVALID_PARAMETER;
81 }
82
83 /* Return the data */
84 Option = MiscGetBootOption(List, Type);
85 if (Option)
86 {
87 /* Extract the string */
88 String = (PWCHAR)((ULONG_PTR)Option + Option->DataOffset);
89 }
90 else
91 {
92 /* No string is present */
93 String = NULL;
94 }
95
96 /* Compute the data size */
97 StringLength = Option->DataSize / sizeof(WCHAR);
98
99 #ifdef _SECURE_BOOT_
100 /* Filter out SecureBoot Options */
101 AppIdentifier = BlGetApplicationIdentifier();
102 Status = BlpBootOptionCallbackString(AppIdentifier, Type, String, StringLength, &String, &StringLength);
103 #else
104 Status = STATUS_SUCCESS;
105 #endif
106
107 /* Check if we have space for one more character */
108 CopyLength = StringLength + 1;
109 if (CopyLength < StringLength)
110 {
111 /* Nope, we'll overflow */
112 CopyLength = -1;
113 Status = STATUS_INTEGER_OVERFLOW;
114 }
115 else
116 {
117 /* Go ahead */
118 Status = STATUS_SUCCESS;
119 }
120
121 /* No overflow? */
122 if (NT_SUCCESS(Status))
123 {
124 /* Check if it's safe to multiply by two */
125 if ((CopyLength * sizeof(WCHAR)) > 0xFFFFFFFF)
126 {
127 /* Nope */
128 CopyLength = -1;
129 Status = STATUS_INTEGER_OVERFLOW;
130 }
131 else
132 {
133 /* We're good, do the multiplication */
134 Status = STATUS_SUCCESS;
135 CopyLength *= sizeof(WCHAR);
136 }
137
138 /* Allocate a copy for the string */
139 if (NT_SUCCESS(Status))
140 {
141 StringCopy = BlMmAllocateHeap(CopyLength);
142 if (StringCopy)
143 {
144 /* NULL-terminate it */
145 RtlCopyMemory(StringCopy,
146 String,
147 CopyLength - sizeof(UNICODE_NULL));
148 StringCopy[CopyLength] = UNICODE_NULL;
149 *Value = StringCopy;
150 Status = STATUS_SUCCESS;
151 }
152 else
153 {
154 /* No memory, fail */
155 Status = STATUS_NO_MEMORY;
156 }
157 }
158 }
159
160 /* All done */
161 return Status;
162 }
163
164 NTSTATUS
165 BlGetBootOptionInteger (
166 _In_ PBL_BCD_OPTION List,
167 _In_ ULONG Type,
168 _Out_ PULONGLONG Value
169 )
170 {
171 NTSTATUS Status;
172 PBL_BCD_OPTION Option;
173 //PGUID AppIdentifier;
174
175 /* Make sure this is a BCD_INTEGER */
176 if ((Type & 0xF000000) != 0x5000000)
177 {
178 return STATUS_INVALID_PARAMETER;
179 }
180
181 /* Return the data */
182 Option = MiscGetBootOption(List, Type);
183 if (Option)
184 {
185 *Value = *(PULONGLONG)((ULONG_PTR)Option + Option->DataOffset);
186 }
187
188 #ifdef _SECURE_BOOT_
189 /* Filter out SecureBoot Options */
190 AppIdentifier = BlGetApplicationIdentifier();
191 Status = BlpBootOptionCallbackULongLong(AppIdentifier, Type, Value);
192 #else
193 /* Option found */
194 Status = Option ? STATUS_SUCCESS : STATUS_NOT_FOUND;
195 #endif
196 return Status;
197 }
198
199 NTSTATUS
200 BlGetBootOptionBoolean (
201 _In_ PBL_BCD_OPTION List,
202 _In_ ULONG Type,
203 _Out_ PBOOLEAN Value
204 )
205 {
206 NTSTATUS Status;
207 PBL_BCD_OPTION Option;
208 //PGUID AppIdentifier;
209
210 /* Make sure this is a BCD_BOOLEAN */
211 if ((Type & 0xF000000) != 0x6000000)
212 {
213 return STATUS_INVALID_PARAMETER;
214 }
215
216 /* Return the data */
217 Option = MiscGetBootOption(List, Type);
218 if (Option)
219 {
220 *Value = *(PBOOLEAN)((ULONG_PTR)Option + Option->DataOffset);
221 }
222
223 #ifdef _SECURE_BOOT_
224 /* Filter out SecureBoot Options */
225 AppIdentifier = BlGetApplicationIdentifier();
226 Status = BlpBootOptionCallbackBoolean(AppIdentifier, Type, Value);
227 #else
228 /* Option found */
229 Status = Option ? STATUS_SUCCESS : STATUS_NOT_FOUND;
230 #endif
231 return Status;
232 }
233
234 /*++
235 * @name BlGetBootOptionListSize
236 *
237 * The BlGetBootOptionListSize routine
238 *
239 * @param BcdOption
240 * UEFI Image Handle for the current loaded application.
241 *
242 * @return Size of the BCD option
243 *
244 *--*/
245 ULONG
246 BlGetBootOptionListSize (
247 _In_ PBL_BCD_OPTION BcdOption
248 )
249 {
250 ULONG Size = 0, NextOffset = 0;
251 PBL_BCD_OPTION NextOption;
252
253 /* Loop all the options*/
254 do
255 {
256 /* Move to the next one */
257 NextOption = (PBL_BCD_OPTION)((ULONG_PTR)BcdOption + NextOffset);
258
259 /* Compute the size of the next one */
260 Size += BlGetBootOptionSize(NextOption);
261
262 /* Update the offset */
263 NextOffset = NextOption->NextEntryOffset;
264 } while (NextOffset != 0);
265
266 /* Return final computed size */
267 return Size;
268 }
269
270 /*++
271 * @name BlGetBootOptionSize
272 *
273 * The BlGetBootOptionSize routine
274 *
275 * @param BcdOption
276 * UEFI Image Handle for the current loaded application.
277 *
278 * @return Size of the BCD option
279 *
280 *--*/
281 ULONG
282 BlGetBootOptionSize (
283 _In_ PBL_BCD_OPTION BcdOption
284 )
285 {
286 ULONG Size, Offset;
287
288 /* Check if there's any data */
289 if (BcdOption->DataOffset != 0)
290 {
291 /* Add the size of the data */
292 Size = BcdOption->DataOffset + BcdOption->DataSize;
293 }
294 else
295 {
296 /* No data, just the structure itself */
297 Size = sizeof(*BcdOption);
298 }
299
300 /* Any associated options? */
301 Offset = BcdOption->ListOffset;
302 if (Offset != 0)
303 {
304 /* Go get those too */
305 Size += BlGetBootOptionListSize((PVOID)((ULONG_PTR)BcdOption + Offset));
306 }
307
308 /* Return the final size */
309 return Size;
310 }