- Implement BmpFwGetApplicationDirectoryPath and most of BmFwInitializeBootDirectoryPath.
[reactos.git] / reactos / boot / environ / app / bootmgr / bootmgr.c
1 /*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Manager
4 * FILE: boot/environ/app/bootmgr.c
5 * PURPOSE: Boot Manager Entrypoint
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "bootmgr.h"
12
13 /* DATA VARIABLES ************************************************************/
14
15 DEFINE_GUID(GUID_WINDOWS_BOOTMGR,
16 0x9DEA862C,
17 0x5CDD,
18 0x4E70,
19 0xAC, 0xC1, 0xF3, 0x2B, 0x34, 0x4D, 0x47, 0x95);
20
21 ULONGLONG ApplicationStartTime;
22 ULONGLONG PostTime;
23 GUID BmApplicationIdentifier;
24 PWCHAR BootDirectory;
25
26 /* FUNCTIONS *****************************************************************/
27
28 NTSTATUS
29 BmpFwGetApplicationDirectoryPath (
30 _In_ PUNICODE_STRING ApplicationDirectoryPath
31 )
32 {
33 NTSTATUS Status;
34 ULONG i, AppPathLength;
35 PWCHAR ApplicationPath, PathCopy;
36
37 /* Clear the incoming string */
38 ApplicationDirectoryPath->Length = 0;
39 ApplicationDirectoryPath->MaximumLength = 0;
40 ApplicationDirectoryPath->Buffer = 0;
41
42 /* Get the boot application path */
43 ApplicationPath = NULL;
44 Status = BlGetBootOptionString(BlpApplicationEntry.BcdData,
45 BcdLibraryString_ApplicationPath,
46 &ApplicationPath);
47 if (NT_SUCCESS(Status))
48 {
49 /* Calculate the length of the application path */
50 for (i = wcslen(ApplicationPath) - 1; i > 0; i--)
51 {
52 /* Keep going until the path separator */
53 if (ApplicationPath[i] == OBJ_NAME_PATH_SEPARATOR)
54 {
55 break;
56 }
57 }
58
59 /* Check if we have space for one more character */
60 AppPathLength = i + 1;
61 if (AppPathLength < i)
62 {
63 /* Nope, we'll overflow */
64 AppPathLength = -1;
65 Status = STATUS_INTEGER_OVERFLOW;
66 }
67 else
68 {
69 /* Go ahead */
70 Status = STATUS_SUCCESS;
71 }
72
73 /* No overflow? */
74 if (NT_SUCCESS(Status))
75 {
76 /* Check if it's safe to multiply by two */
77 if ((AppPathLength * sizeof(WCHAR)) > 0xFFFFFFFF)
78 {
79 /* Nope */
80 AppPathLength = -1;
81 Status = STATUS_INTEGER_OVERFLOW;
82 }
83 else
84 {
85 /* We're good, do the multiplication */
86 Status = STATUS_SUCCESS;
87 AppPathLength *= sizeof(WCHAR);
88 }
89
90 /* Allocate a copy for the string */
91 if (NT_SUCCESS(Status))
92 {
93 PathCopy = BlMmAllocateHeap(AppPathLength);
94 if (PathCopy)
95 {
96 /* NULL-terminate it */
97 RtlCopyMemory(PathCopy,
98 ApplicationPath,
99 AppPathLength - sizeof(UNICODE_NULL));
100 PathCopy[AppPathLength] = UNICODE_NULL;
101
102 /* Finally, initialize the outoing string */
103 RtlInitUnicodeString(ApplicationDirectoryPath, PathCopy);
104 }
105 else
106 {
107 /* No memory, fail */
108 Status = STATUS_NO_MEMORY;
109 }
110 }
111 }
112 }
113
114 /* Check if we had an application path */
115 if (ApplicationPath)
116 {
117 /* No longer need this, free it */
118 BlMmFreeHeap(ApplicationPath);
119 }
120
121 /* All done! */
122 return Status;
123
124 }
125 NTSTATUS
126 BmFwInitializeBootDirectoryPath (
127 VOID
128 )
129 {
130 PWCHAR FinalPath;
131 NTSTATUS Status;
132 PWCHAR BcdDirectory;
133 UNICODE_STRING BcdPath;
134 ULONG FinalSize;
135 ULONG FileHandle, DeviceHandle;
136
137 /* Initialize everything for failure */
138 BcdPath.MaximumLength = 0;
139 BcdPath.Buffer = NULL;
140 BcdDirectory = NULL;
141 FinalPath = NULL;
142 FileHandle = -1;
143 DeviceHandle = -1;
144
145 /* Try to open the boot device */
146 Status = BlpDeviceOpen(BlpBootDevice, 1u, 0, &DeviceHandle);
147 if (!NT_SUCCESS(Status))
148 {
149 EfiPrintf(L"Device open failed: %lx\r\n", Status);
150 goto Quickie;
151 }
152
153 /* Get the directory path */
154 Status = BmpFwGetApplicationDirectoryPath(&BcdPath);
155 BcdDirectory = BcdPath.Buffer;
156 if (!NT_SUCCESS(Status))
157 {
158 EfiPrintf(L"path failed: %lx\n", Status);
159 goto Quickie;
160 }
161
162 /* Add the BCD file name to it */
163 FinalSize = BcdPath.MaximumLength + sizeof(L"\\BCD") - sizeof(UNICODE_NULL);
164 if (FinalSize < BcdPath.MaximumLength)
165 {
166 goto Quickie;
167 }
168
169 /* Allocate space for the final path */
170 FinalPath = BlMmAllocateHeap(FinalSize);
171 if (!FinalPath)
172 {
173 goto Quickie;
174 }
175
176 /* Build it */
177 RtlZeroMemory(FinalPath, FinalSize);
178 RtlCopyMemory(FinalPath, BcdDirectory, BcdPath.MaximumLength);
179 wcsncat(FinalPath, L"\\BCD", FinalSize / sizeof(WCHAR));
180
181 /* Try to open the file */
182 EfiPrintf(L"Opening: %s\r\n", FinalPath);
183 #if 0
184 Status = BlFileOpen(DeviceHandle, FinalPath, 1u, &FileHandle);
185 if (!NT_SUCCESS(Status))
186 {
187 BootDirectory = BcdDirectory;
188 goto Quickie;
189 }
190
191 BootDirectory = L"\\EFI\\Microsoft\\Boot";
192 #endif
193
194 Quickie:
195 /* Free all the allocations we made */
196 if (BcdDirectory)
197 {
198 Status = BlMmFreeHeap(BcdDirectory);
199 }
200 if (FinalPath)
201 {
202 Status = BlMmFreeHeap(FinalPath);
203 }
204
205 /* Close the BCD file */
206 if (FileHandle != -1)
207 {
208 //Status = BlFileClose(FileHandle);
209 }
210
211 /* Close the boot device */
212 if (DeviceHandle != -1)
213 {
214 Status = BlDeviceClose(DeviceHandle);
215 }
216
217 /* Return back to the caller */
218 return Status;
219 }
220
221
222 /*++
223 * @name BmMain
224 *
225 * The BmMain function implements the Windows Boot Application entrypoint for
226 * the Boot Manager.
227 *
228 * @param BootParameters
229 * Pointer to the Boot Application Parameter Block.
230 *
231 * @return NT_SUCCESS if the image was loaded correctly, relevant error code
232 * otherwise.
233 *
234 *--*/
235 NTSTATUS
236 BmMain (
237 _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
238 )
239 {
240 NTSTATUS Status;
241 BL_LIBRARY_PARAMETERS LibraryParameters;
242 PBL_RETURN_ARGUMENTS ReturnArguments;
243 BOOLEAN RebootOnError;
244 PGUID AppIdentifier;
245 // HANDLE BcdHandle;
246
247 EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\n");
248
249 /* Reading the BCD can change this later on */
250 RebootOnError = FALSE;
251
252 /* Save the start/end-of-POST time */
253 ApplicationStartTime = __rdtsc();
254 PostTime = ApplicationStartTime;
255
256 /* Setup the boot library parameters for this application */
257 BlSetupDefaultParameters(&LibraryParameters);
258 LibraryParameters.TranslationType = BlNone;
259 LibraryParameters.LibraryFlags = 0x400 | 0x8;
260 LibraryParameters.MinimumAllocationCount = 16;
261 LibraryParameters.MinimumHeapSize = 512 * 1024;
262
263 /* Initialize the boot library */
264 Status = BlInitializeLibrary(BootParameters, &LibraryParameters);
265 if (!NT_SUCCESS(Status))
266 {
267 /* Check for failure due to invalid application entry */
268 if (Status != STATUS_INVALID_PARAMETER_9)
269 {
270 /* Specifically print out what happened */
271 EfiPrintf(L"BlInitializeLibrary failed 0x%x\r\n", Status);
272 }
273
274 /* Go to exit path */
275 goto Quickie;
276 }
277
278 /* Get the application identifier */
279 AppIdentifier = BlGetApplicationIdentifier();
280 if (!AppIdentifier)
281 {
282 /* None was given, so set our default one */
283 AppIdentifier = (PGUID)&GUID_WINDOWS_BOOTMGR;
284 }
285
286 /* Save our identifier */
287 BmApplicationIdentifier = *AppIdentifier;
288
289 /* Initialize the file system to open a handle to our root boot directory */
290 BmFwInitializeBootDirectoryPath();
291
292 //Status = BmOpenDataStore(&BcdHandle);
293
294 EfiPrintf(L"We are A-OK!\r\n");
295 EfiStall(10000000);
296
297 Quickie:
298 /* Check if we should reboot */
299 if ((RebootOnError) ||
300 (BlpApplicationEntry.Flags & BL_APPLICATION_ENTRY_REBOOT_ON_ERROR))
301 {
302 /* Reboot the box */
303 BlFwReboot();
304 Status = STATUS_SUCCESS;
305 }
306 else
307 {
308 /* Return back to the caller with the error argument encoded */
309 ReturnArguments = (PVOID)((ULONG_PTR)BootParameters + BootParameters->ReturnArgumentsOffset);
310 ReturnArguments->Version = BL_RETURN_ARGUMENTS_VERSION;
311 ReturnArguments->Status = Status;
312
313 /* Tear down the boot library*/
314 BlDestroyLibrary();
315 }
316
317 /* Return back status */
318 return Status;
319 }
320