3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Windows-compatible NT OS Setup Loader.
5 * COPYRIGHT: Copyright 2009-2019 Aleksey Bragin <aleksey@reactos.org>
9 #include <ndk/ldrtypes.h>
10 #include <arc/setupblk.h>
15 DBG_DEFAULT_CHANNEL(WINDOWS
);
17 #define TAG_BOOT_OPTIONS 'pOtB'
22 IN USHORT VersionToBoot
,
23 OUT PLOADER_PARAMETER_BLOCK
* OutLoaderBlock
);
26 SetupLdrLoadNlsData(PLOADER_PARAMETER_BLOCK LoaderBlock
, HINF InfHandle
, PCSTR SearchPath
)
28 INFCONTEXT InfContext
;
29 PCSTR AnsiName
, OemName
, LangName
;
31 /* Get ANSI codepage file */
32 if (!InfFindFirstLine(InfHandle
, "NLS", "AnsiCodepage", &InfContext
))
34 ERR("Failed to find 'NLS/AnsiCodepage'\n");
37 if (!InfGetDataField(&InfContext
, 1, &AnsiName
))
39 ERR("Failed to get load options\n");
43 /* Get OEM codepage file */
44 if (!InfFindFirstLine(InfHandle
, "NLS", "OemCodepage", &InfContext
))
46 ERR("Failed to find 'NLS/AnsiCodepage'\n");
49 if (!InfGetDataField(&InfContext
, 1, &OemName
))
51 ERR("Failed to get load options\n");
55 if (!InfFindFirstLine(InfHandle
, "NLS", "UnicodeCasetable", &InfContext
))
57 ERR("Failed to find 'NLS/AnsiCodepage'\n");
60 if (!InfGetDataField(&InfContext
, 1, &LangName
))
62 ERR("Failed to get load options\n");
66 TRACE("NLS data '%s' '%s' '%s'\n", AnsiName
, OemName
, LangName
);
70 BOOLEAN Success
= WinLdrLoadNLSData(LoaderBlock
, SearchPath
, AnsiName
, OemName
, LangName
);
72 TRACE("NLS data loading %s\n", Success
? "successful" : "failed");
75 WinLdrLoadNLSData(LoaderBlock
, SearchPath
, AnsiName
, OemName
, LangName
);
78 /* TODO: Load OEM HAL font */
84 SetupLdrInitErrataInf(
85 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock
,
89 INFCONTEXT InfContext
;
93 CHAR ErrataFilePath
[MAX_PATH
];
95 /* Retrieve the INF file name value */
96 if (!InfFindFirstLine(InfHandle
, "BiosInfo", "InfName", &InfContext
))
98 WARN("Failed to find 'BiosInfo/InfName'\n");
101 if (!InfGetDataField(&InfContext
, 1, &FileName
))
103 WARN("Failed to read 'InfName' value\n");
107 RtlStringCbCopyA(ErrataFilePath
, sizeof(ErrataFilePath
), SystemRoot
);
108 RtlStringCbCatA(ErrataFilePath
, sizeof(ErrataFilePath
), FileName
);
110 /* Load the INF file */
111 PhysicalBase
= WinLdrLoadModule(ErrataFilePath
, &FileSize
, LoaderRegistryData
);
114 WARN("Could not load '%s'\n", ErrataFilePath
);
118 LoaderBlock
->Extension
->EmInfFileImage
= PaToVa(PhysicalBase
);
119 LoaderBlock
->Extension
->EmInfFileSize
= FileSize
;
125 SetupLdrScanBootDrivers(PLIST_ENTRY BootDriverListHead
, HINF InfHandle
, PCSTR SearchPath
)
127 INFCONTEXT InfContext
, dirContext
;
129 PCSTR Media
, DriverName
, dirIndex
, ImagePath
;
130 WCHAR ServiceName
[256];
131 WCHAR ImagePathW
[256];
133 /* Open inf section */
134 if (!InfFindFirstLine(InfHandle
, "SourceDisksFiles", NULL
, &InfContext
))
137 /* Load all listed boot drivers */
140 if (InfGetDataField(&InfContext
, 7, &Media
) &&
141 InfGetDataField(&InfContext
, 0, &DriverName
) &&
142 InfGetDataField(&InfContext
, 13, &dirIndex
))
144 if ((strcmp(Media
, "x") == 0) &&
145 InfFindFirstLine(InfHandle
, "Directories", dirIndex
, &dirContext
) &&
146 InfGetDataField(&dirContext
, 1, &ImagePath
))
148 /* Convert name to widechar */
149 swprintf(ServiceName
, L
"%S", DriverName
);
151 /* Prepare image path */
152 swprintf(ImagePathW
, L
"%S", ImagePath
);
153 wcscat(ImagePathW
, L
"\\");
154 wcscat(ImagePathW
, ServiceName
);
156 /* Remove .sys extension */
157 ServiceName
[wcslen(ServiceName
) - 4] = 0;
159 /* Add it to the list */
160 Success
= WinLdrAddDriverToList(BootDriverListHead
,
161 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
166 ERR("Could not add boot driver '%s', '%s'\n", SearchPath
, DriverName
);
171 } while (InfFindNextLine(&InfContext
, &InfContext
));
175 /* SETUP STARTER **************************************************************/
185 PCSTR SystemPartition
;
187 CHAR FileName
[MAX_PATH
];
188 CHAR BootPath
[MAX_PATH
];
189 CHAR BootOptions2
[256];
192 BOOLEAN BootFromFloppy
;
196 INFCONTEXT InfContext
;
197 PLOADER_PARAMETER_BLOCK LoaderBlock
;
198 PSETUP_LOADER_BLOCK SetupBlock
;
201 static PCSTR SourcePaths
[] =
203 "", /* Only for floppy boot */
206 #elif defined(_M_MPPC)
208 #elif defined(_M_MRX000)
215 /* Retrieve the (mandatory) system partition */
216 SystemPartition
= GetArgumentValue(Argc
, Argv
, "SystemPartition");
217 if (!SystemPartition
|| !*SystemPartition
)
219 ERR("No 'SystemPartition' specified, aborting!\n");
223 UiDrawStatusText("Setup is loading...");
226 UiDrawProgressBarCenter(1, 100, "Loading ReactOS Setup...");
228 /* Retrieve the system path */
229 *BootPath
= ANSI_NULL
;
230 ArgValue
= GetArgumentValue(Argc
, Argv
, "SystemPath");
233 RtlStringCbCopyA(BootPath
, sizeof(BootPath
), ArgValue
);
238 * IMPROVE: I don't want to use the SystemPartition here as a
239 * default choice because I can do it after (see few lines below).
240 * Instead I reset BootPath here so that we can build the full path
241 * using the general code from below.
243 // RtlStringCbCopyA(BootPath, sizeof(BootPath), SystemPartition);
244 *BootPath
= ANSI_NULL
;
248 * Check whether BootPath is a full path
249 * and if not, create a full boot path.
251 * See FsOpenFile for the technique used.
253 if (strrchr(BootPath
, ')') == NULL
)
255 /* Temporarily save the boot path */
256 RtlStringCbCopyA(FileName
, sizeof(FileName
), BootPath
);
258 /* This is not a full path: prepend the SystemPartition */
259 RtlStringCbCopyA(BootPath
, sizeof(BootPath
), SystemPartition
);
261 /* Append a path separator if needed */
262 if (*FileName
!= '\\' && *FileName
!= '/')
263 RtlStringCbCatA(BootPath
, sizeof(BootPath
), "\\");
265 /* Append the remaining path */
266 RtlStringCbCatA(BootPath
, sizeof(BootPath
), FileName
);
269 /* Append a path separator if needed */
270 if (!*BootPath
|| BootPath
[strlen(BootPath
) - 1] != '\\')
271 RtlStringCbCatA(BootPath
, sizeof(BootPath
), "\\");
273 TRACE("BootPath: '%s'\n", BootPath
);
275 /* Retrieve the boot options */
276 *BootOptions2
= ANSI_NULL
;
277 ArgValue
= GetArgumentValue(Argc
, Argv
, "Options");
278 if (ArgValue
&& *ArgValue
)
279 RtlStringCbCopyA(BootOptions2
, sizeof(BootOptions2
), ArgValue
);
281 TRACE("BootOptions: '%s'\n", BootOptions2
);
283 /* Check if a ramdisk file was given */
284 File
= strstr(BootOptions2
, "/RDPATH=");
287 /* Copy the file name and everything else after it */
288 RtlStringCbCopyA(FileName
, sizeof(FileName
), File
+ 8);
291 *strstr(FileName
, " ") = ANSI_NULL
;
293 /* Load the ramdisk */
294 Status
= RamDiskLoadVirtualFile(FileName
, SystemPartition
);
295 if (Status
!= ESUCCESS
)
297 UiMessageBox("Failed to load RAM disk file %s", FileName
);
302 /* Check if we booted from floppy */
303 BootFromFloppy
= strstr(BootPath
, "fdisk") != NULL
;
305 /* Open 'txtsetup.sif' from any of source paths */
306 File
= BootPath
+ strlen(BootPath
);
307 for (i
= BootFromFloppy
? 0 : 1; ; i
++)
309 SystemPath
= SourcePaths
[i
];
312 UiMessageBox("Failed to open txtsetup.sif");
315 RtlStringCbCopyA(File
, sizeof(BootPath
) - (File
- BootPath
)*sizeof(CHAR
), SystemPath
);
316 RtlStringCbCopyA(FileName
, sizeof(FileName
), BootPath
);
317 RtlStringCbCatA(FileName
, sizeof(FileName
), "txtsetup.sif");
318 if (InfOpenFile(&InfHandle
, FileName
, &ErrorLine
))
324 TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath
, SystemPath
);
326 /* Get Load options - debug and non-debug */
327 if (!InfFindFirstLine(InfHandle
, "SetupData", "OsLoadOptions", &InfContext
))
329 ERR("Failed to find 'SetupData/OsLoadOptions'\n");
333 if (!InfGetDataField(&InfContext
, 1, &LoadOptions
))
335 ERR("Failed to get load options\n");
340 /* Get debug load options and use them */
341 if (InfFindFirstLine(InfHandle
, "SetupData", "DbgOsLoadOptions", &InfContext
))
343 PCSTR DbgLoadOptions
;
345 if (InfGetDataField(&InfContext
, 1, &DbgLoadOptions
))
346 LoadOptions
= DbgLoadOptions
;
350 /* Copy LoadOptions (original string will be freed) */
351 BootOptions
= FrLdrTempAlloc(strlen(LoadOptions
) + 1, TAG_BOOT_OPTIONS
);
353 strcpy(BootOptions
, LoadOptions
);
355 TRACE("BootOptions: '%s'\n", BootOptions
);
357 /* Allocate and minimally-initialize the Loader Parameter Block */
358 AllocateAndInitLPB(_WIN32_WINNT_WS03
, &LoaderBlock
);
360 /* Allocate and initialize setup loader block */
361 SetupBlock
= &WinLdrSystemBlock
->SetupBlock
;
362 LoaderBlock
->SetupLdrBlock
= SetupBlock
;
364 /* Set textmode setup flag */
365 SetupBlock
->Flags
= SETUPLDR_TEXT_MODE
;
367 /* Load the system hive "setupreg.hiv" for setup */
369 UiDrawProgressBarCenter(15, 100, "Loading setup system hive...");
370 Success
= WinLdrInitSystemHive(LoaderBlock
, BootPath
, TRUE
);
371 TRACE("Setup SYSTEM hive %s\n", (Success
? "loaded" : "not loaded"));
372 /* Bail out if failure */
376 /* Load NLS data, they are in the System32 directory of the installation medium */
377 RtlStringCbCopyA(FileName
, sizeof(FileName
), BootPath
);
378 RtlStringCbCatA(FileName
, sizeof(FileName
), "system32\\");
379 SetupLdrLoadNlsData(LoaderBlock
, InfHandle
, FileName
);
381 /* Load the Firmware Errata file from the installation medium */
382 Success
= SetupLdrInitErrataInf(LoaderBlock
, InfHandle
, BootPath
);
383 TRACE("Firmware Errata file %s\n", (Success
? "loaded" : "not loaded"));
384 /* Not necessarily fatal if not found - carry on going */
386 // UiDrawStatusText("Press F6 if you need to install a 3rd-party SCSI or RAID driver...");
388 /* Get a list of boot drivers */
389 SetupLdrScanBootDrivers(&LoaderBlock
->BootDriverListHead
, InfHandle
, BootPath
);
391 /* Close the inf file */
392 InfCloseFile(InfHandle
);
394 UiDrawStatusText("The Setup program is starting...");
396 /* Load ReactOS Setup */
397 return LoadAndBootWindowsCommon(_WIN32_WINNT_WS03
,