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'
20 VOID
AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK
*OutLoaderBlock
);
23 SetupLdrLoadNlsData(PLOADER_PARAMETER_BLOCK LoaderBlock
, HINF InfHandle
, PCSTR SearchPath
)
25 INFCONTEXT InfContext
;
26 PCSTR AnsiName
, OemName
, LangName
;
28 /* Get ANSI codepage file */
29 if (!InfFindFirstLine(InfHandle
, "NLS", "AnsiCodepage", &InfContext
))
31 ERR("Failed to find 'NLS/AnsiCodepage'\n");
34 if (!InfGetDataField(&InfContext
, 1, &AnsiName
))
36 ERR("Failed to get load options\n");
40 /* Get OEM codepage file */
41 if (!InfFindFirstLine(InfHandle
, "NLS", "OemCodepage", &InfContext
))
43 ERR("Failed to find 'NLS/AnsiCodepage'\n");
46 if (!InfGetDataField(&InfContext
, 1, &OemName
))
48 ERR("Failed to get load options\n");
52 if (!InfFindFirstLine(InfHandle
, "NLS", "UnicodeCasetable", &InfContext
))
54 ERR("Failed to find 'NLS/AnsiCodepage'\n");
57 if (!InfGetDataField(&InfContext
, 1, &LangName
))
59 ERR("Failed to get load options\n");
63 TRACE("NLS data '%s' '%s' '%s'\n", AnsiName
, OemName
, LangName
);
67 BOOLEAN Success
= WinLdrLoadNLSData(LoaderBlock
, SearchPath
, AnsiName
, OemName
, LangName
);
68 TRACE("NLS data loading %s\n", Success
? "successful" : "failed");
71 WinLdrLoadNLSData(LoaderBlock
, SearchPath
, AnsiName
, OemName
, LangName
);
74 /* TODO: Load OEM HAL font */
79 SetupLdrScanBootDrivers(PLIST_ENTRY BootDriverListHead
, HINF InfHandle
, PCSTR SearchPath
)
81 INFCONTEXT InfContext
, dirContext
;
83 PCSTR Media
, DriverName
, dirIndex
, ImagePath
;
84 WCHAR ServiceName
[256];
85 WCHAR ImagePathW
[256];
87 /* Open inf section */
88 if (!InfFindFirstLine(InfHandle
, "SourceDisksFiles", NULL
, &InfContext
))
91 /* Load all listed boot drivers */
94 if (InfGetDataField(&InfContext
, 7, &Media
) &&
95 InfGetDataField(&InfContext
, 0, &DriverName
) &&
96 InfGetDataField(&InfContext
, 13, &dirIndex
))
98 if ((strcmp(Media
, "x") == 0) &&
99 InfFindFirstLine(InfHandle
, "Directories", dirIndex
, &dirContext
) &&
100 InfGetDataField(&dirContext
, 1, &ImagePath
))
102 /* Convert name to widechar */
103 swprintf(ServiceName
, L
"%S", DriverName
);
105 /* Prepare image path */
106 swprintf(ImagePathW
, L
"%S", ImagePath
);
107 wcscat(ImagePathW
, L
"\\");
108 wcscat(ImagePathW
, ServiceName
);
110 /* Remove .sys extension */
111 ServiceName
[wcslen(ServiceName
) - 4] = 0;
113 /* Add it to the list */
114 Success
= WinLdrAddDriverToList(BootDriverListHead
,
115 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
120 ERR("Could not add boot driver '%s', '%s'\n", SearchPath
, DriverName
);
125 } while (InfFindNextLine(&InfContext
, &InfContext
));
129 /* SETUP STARTER **************************************************************/
141 CHAR BootOptions2
[256];
144 BOOLEAN BootFromFloppy
;
148 INFCONTEXT InfContext
;
149 PLOADER_PARAMETER_BLOCK LoaderBlock
;
150 PSETUP_LOADER_BLOCK SetupBlock
;
153 static PCSTR SourcePaths
[] =
155 "", /* Only for floppy boot */
158 #elif defined(_M_MPPC)
160 #elif defined(_M_MRX000)
167 UiDrawStatusText("Setup is loading...");
170 UiDrawProgressBarCenter(1, 100, "Loading ReactOS Setup...");
172 /* Retrieve the system path */
173 *BootPath
= ANSI_NULL
;
174 ArgValue
= GetArgumentValue(Argc
, Argv
, "SystemPath");
177 RtlStringCbCopyA(BootPath
, sizeof(BootPath
), ArgValue
);
182 * IMPROVE: I don't want to call MachDiskGetBootPath here as a
183 * default choice because I can call it after (see few lines below).
184 * Instead I reset BootPath here so that we can build the full path
185 * using the general code from below.
187 // MachDiskGetBootPath(BootPath, sizeof(BootPath));
188 // RtlStringCbCopyA(BootPath, sizeof(BootPath), ArgValue);
189 *BootPath
= ANSI_NULL
;
193 * Check whether BootPath is a full path
194 * and if not, create a full boot path.
196 * See FsOpenFile for the technique used.
198 if (strrchr(BootPath
, ')') == NULL
)
200 /* Temporarily save the boot path */
201 RtlStringCbCopyA(FileName
, sizeof(FileName
), BootPath
);
203 /* This is not a full path. Use the current (i.e. boot) device. */
204 MachDiskGetBootPath(BootPath
, sizeof(BootPath
));
206 /* Append a path separator if needed */
207 if (*FileName
!= '\\' && *FileName
!= '/')
208 RtlStringCbCatA(BootPath
, sizeof(BootPath
), "\\");
210 /* Append the remaining path */
211 RtlStringCbCatA(BootPath
, sizeof(BootPath
), FileName
);
214 /* Append a backslash if needed */
215 if (!*BootPath
|| BootPath
[strlen(BootPath
) - 1] != '\\')
216 RtlStringCbCatA(BootPath
, sizeof(BootPath
), "\\");
218 TRACE("BootPath: '%s'\n", BootPath
);
220 /* Retrieve the boot options */
221 *BootOptions2
= ANSI_NULL
;
222 ArgValue
= GetArgumentValue(Argc
, Argv
, "Options");
224 RtlStringCbCopyA(BootOptions2
, sizeof(BootOptions2
), ArgValue
);
226 TRACE("BootOptions: '%s'\n", BootOptions2
);
228 /* Check if a ramdisk file was given */
229 File
= strstr(BootOptions2
, "/RDPATH=");
232 /* Copy the file name and everything else after it */
233 RtlStringCbCopyA(FileName
, sizeof(FileName
), File
+ 8);
236 *strstr(FileName
, " ") = ANSI_NULL
;
238 /* Load the ramdisk */
239 if (!RamDiskLoadVirtualFile(FileName
))
241 UiMessageBox("Failed to load RAM disk file %s", FileName
);
246 /* Check if we booted from floppy */
247 BootFromFloppy
= strstr(BootPath
, "fdisk") != NULL
;
249 /* Open 'txtsetup.sif' from any of source paths */
250 File
= BootPath
+ strlen(BootPath
);
251 for (i
= BootFromFloppy
? 0 : 1; ; i
++)
253 SystemPath
= SourcePaths
[i
];
256 UiMessageBox("Failed to open txtsetup.sif");
259 RtlStringCbCopyA(File
, sizeof(BootPath
) - (File
- BootPath
)*sizeof(CHAR
), SystemPath
);
260 RtlStringCbCopyA(FileName
, sizeof(FileName
), BootPath
);
261 RtlStringCbCatA(FileName
, sizeof(FileName
), "txtsetup.sif");
262 if (InfOpenFile(&InfHandle
, FileName
, &ErrorLine
))
268 TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath
, SystemPath
);
270 /* Get Load options - debug and non-debug */
271 if (!InfFindFirstLine(InfHandle
, "SetupData", "OsLoadOptions", &InfContext
))
273 ERR("Failed to find 'SetupData/OsLoadOptions'\n");
277 if (!InfGetDataField(&InfContext
, 1, &LoadOptions
))
279 ERR("Failed to get load options\n");
284 /* Get debug load options and use them */
285 if (InfFindFirstLine(InfHandle
, "SetupData", "DbgOsLoadOptions", &InfContext
))
287 PCSTR DbgLoadOptions
;
289 if (InfGetDataField(&InfContext
, 1, &DbgLoadOptions
))
290 LoadOptions
= DbgLoadOptions
;
294 /* Copy loadoptions (original string will be freed) */
295 BootOptions
= FrLdrTempAlloc(strlen(LoadOptions
) + 1, TAG_BOOT_OPTIONS
);
297 strcpy(BootOptions
, LoadOptions
);
299 TRACE("BootOptions: '%s'\n", BootOptions
);
301 /* Allocate and minimalist-initialize LPB */
302 AllocateAndInitLPB(&LoaderBlock
);
304 /* Allocate and initialize setup loader block */
305 SetupBlock
= &WinLdrSystemBlock
->SetupBlock
;
306 LoaderBlock
->SetupLdrBlock
= SetupBlock
;
308 /* Set textmode setup flag */
309 SetupBlock
->Flags
= SETUPLDR_TEXT_MODE
;
311 /* Load the system hive "setupreg.hiv" for setup */
313 UiDrawProgressBarCenter(15, 100, "Loading setup system hive...");
314 Success
= WinLdrInitSystemHive(LoaderBlock
, BootPath
, TRUE
);
315 TRACE("Setup SYSTEM hive %s\n", (Success
? "loaded" : "not loaded"));
316 /* Bail out if failure */
320 /* Load NLS data, they are in the System32 directory of the installation medium */
321 RtlStringCbCopyA(FileName
, sizeof(FileName
), BootPath
);
322 RtlStringCbCatA(FileName
, sizeof(FileName
), "system32\\");
323 SetupLdrLoadNlsData(LoaderBlock
, InfHandle
, FileName
);
325 // UiDrawStatusText("Press F6 if you need to install a 3rd-party SCSI or RAID driver...");
327 /* Get a list of boot drivers */
328 SetupLdrScanBootDrivers(&LoaderBlock
->BootDriverListHead
, InfHandle
, BootPath
);
330 /* Close the inf file */
331 InfCloseFile(InfHandle
);
333 UiDrawStatusText("The Setup program is starting...");
335 /* Load ReactOS Setup */
336 return LoadAndBootWindowsCommon(_WIN32_WINNT_WS03
,