Minor changes for ATAPI Srb Functions
[reactos.git] / boot / freeldr / freeldr / ntldr / setupldr.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2009 Aleksey Bragin <aleksey@reactos.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <freeldr.h>
22
23 #include <ndk/ldrtypes.h>
24 #include <arc/setupblk.h>
25
26 #include <debug.h>
27
28 DBG_DEFAULT_CHANNEL(WINDOWS);
29 #define TAG_BOOT_OPTIONS 'pOtB'
30
31 void
32 WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock);
33
34 VOID
35 WinLdrSetProcessorContext(void);
36
37 // TODO: Move to .h
38 VOID AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock);
39
40 static VOID
41 SetupLdrLoadNlsData(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, LPCSTR SearchPath)
42 {
43 INFCONTEXT InfContext;
44 BOOLEAN Success;
45 LPCSTR AnsiName, OemName, LangName;
46
47 /* Get ANSI codepage file */
48 if (!InfFindFirstLine(InfHandle, "NLS", "AnsiCodepage", &InfContext))
49 {
50 ERR("Failed to find 'NLS/AnsiCodepage'\n");
51 return;
52 }
53 if (!InfGetDataField(&InfContext, 1, &AnsiName))
54 {
55 ERR("Failed to get load options\n");
56 return;
57 }
58
59 /* Get OEM codepage file */
60 if (!InfFindFirstLine(InfHandle, "NLS", "OemCodepage", &InfContext))
61 {
62 ERR("Failed to find 'NLS/AnsiCodepage'\n");
63 return;
64 }
65 if (!InfGetDataField(&InfContext, 1, &OemName))
66 {
67 ERR("Failed to get load options\n");
68 return;
69 }
70
71 if (!InfFindFirstLine(InfHandle, "NLS", "UnicodeCasetable", &InfContext))
72 {
73 ERR("Failed to find 'NLS/AnsiCodepage'\n");
74 return;
75 }
76 if (!InfGetDataField(&InfContext, 1, &LangName))
77 {
78 ERR("Failed to get load options\n");
79 return;
80 }
81
82 Success = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
83 TRACE("NLS data loading %s\n", Success ? "successful" : "failed");
84 }
85
86 static VOID
87 SetupLdrScanBootDrivers(PLIST_ENTRY BootDriverListHead, HINF InfHandle, LPCSTR SearchPath)
88 {
89 INFCONTEXT InfContext, dirContext;
90 BOOLEAN Success;
91 LPCSTR Media, DriverName, dirIndex, ImagePath;
92 WCHAR ServiceName[256];
93 WCHAR ImagePathW[256];
94
95 /* Open inf section */
96 if (!InfFindFirstLine(InfHandle, "SourceDisksFiles", NULL, &InfContext))
97 return;
98
99 /* Load all listed boot drivers */
100 do
101 {
102 if (InfGetDataField(&InfContext, 7, &Media) &&
103 InfGetDataField(&InfContext, 0, &DriverName) &&
104 InfGetDataField(&InfContext, 13, &dirIndex))
105 {
106 if ((strcmp(Media, "x") == 0) &&
107 InfFindFirstLine(InfHandle, "Directories", dirIndex, &dirContext) &&
108 InfGetDataField(&dirContext, 1, &ImagePath))
109 {
110 /* Convert name to widechar */
111 swprintf(ServiceName, L"%S", DriverName);
112
113 /* Prepare image path */
114 swprintf(ImagePathW, L"%S", ImagePath);
115 wcscat(ImagePathW, L"\\");
116 wcscat(ImagePathW, ServiceName);
117
118 /* Remove .sys extension */
119 ServiceName[wcslen(ServiceName) - 4] = 0;
120
121 /* Add it to the list */
122 Success = WinLdrAddDriverToList(BootDriverListHead,
123 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
124 ImagePathW,
125 ServiceName);
126 if (!Success)
127 {
128 ERR("could not add boot driver %s, %s\n", SearchPath, DriverName);
129 return;
130 }
131 }
132 }
133 } while (InfFindNextLine(&InfContext, &InfContext));
134 }
135
136 VOID
137 LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
138 IN USHORT OperatingSystemVersion)
139 {
140 ULONG_PTR SectionId;
141 PCSTR SectionName = OperatingSystem->SystemPartition;
142 CHAR SettingsValue[80];
143 BOOLEAN HasSection;
144 CHAR BootOptions2[256];
145 PCHAR File;
146 CHAR FileName[512];
147 CHAR BootPath[512];
148 LPCSTR LoadOptions;
149 LPSTR BootOptions;
150 BOOLEAN BootFromFloppy;
151 ULONG i, ErrorLine;
152 HINF InfHandle;
153 INFCONTEXT InfContext;
154 PLOADER_PARAMETER_BLOCK LoaderBlock;
155 PSETUP_LOADER_BLOCK SetupBlock;
156 LPCSTR SystemPath;
157 LPCSTR SourcePaths[] =
158 {
159 "", /* Only for floppy boot */
160 #if defined(_M_IX86)
161 "I386\\",
162 #elif defined(_M_MPPC)
163 "PPC\\",
164 #elif defined(_M_MRX000)
165 "MIPS\\",
166 #endif
167 "reactos\\",
168 NULL
169 };
170
171 /* Get OS setting value */
172 SettingsValue[0] = ANSI_NULL;
173 IniOpenSection("Operating Systems", &SectionId);
174 IniReadSettingByName(SectionId, SectionName, SettingsValue, sizeof(SettingsValue));
175
176 /* Open the operating system section specified in the .ini file */
177 HasSection = IniOpenSection(SectionName, &SectionId);
178
179 UiDrawBackdrop();
180 UiDrawProgressBarCenter(1, 100, "Loading ReactOS Setup...");
181
182 /* Read the system path is set in the .ini file */
183 if (!HasSection ||
184 !IniReadSettingByName(SectionId, "SystemPath", BootPath, sizeof(BootPath)))
185 {
186 /*
187 * IMPROVE: I don't want to call MachDiskGetBootPath here as a
188 * default choice because I can call it after (see few lines below).
189 * Also doing the strcpy call as it is done in winldr.c is not
190 * really what we want. Instead I reset BootPath here so that
191 * we can build the full path using the general code from below.
192 */
193 // MachDiskGetBootPath(BootPath, sizeof(BootPath));
194 // strcpy(BootPath, SectionName);
195 BootPath[0] = '\0';
196 }
197
198 /*
199 * Check whether BootPath is a full path
200 * and if not, create a full boot path.
201 *
202 * See FsOpenFile for the technique used.
203 */
204 if (strrchr(BootPath, ')') == NULL)
205 {
206 /* Temporarily save the boot path */
207 strcpy(FileName, BootPath);
208
209 /* This is not a full path. Use the current (i.e. boot) device. */
210 MachDiskGetBootPath(BootPath, sizeof(BootPath));
211
212 /* Append a path separator if needed */
213 if (FileName[0] != '\\' && FileName[0] != '/')
214 strcat(BootPath, "\\");
215
216 /* Append the remaining path */
217 strcat(BootPath, FileName);
218 }
219
220 /* Append a backslash if needed */
221 if ((strlen(BootPath) == 0) || BootPath[strlen(BootPath) - 1] != '\\')
222 strcat(BootPath, "\\");
223
224 /* Read booting options */
225 if (!HasSection || !IniReadSettingByName(SectionId, "Options", BootOptions2, sizeof(BootOptions2)))
226 {
227 /* Get options after the title */
228 PCSTR p = SettingsValue;
229 while (*p == ' ' || *p == '"')
230 p++;
231 while (*p != '\0' && *p != '"')
232 p++;
233 strcpy(BootOptions2, p);
234 TRACE("BootOptions: '%s'\n", BootOptions2);
235 }
236
237 /* Check if a ramdisk file was given */
238 File = strstr(BootOptions2, "/RDPATH=");
239 if (File)
240 {
241 /* Copy the file name and everything else after it */
242 strcpy(FileName, File + 8);
243
244 /* Null-terminate */
245 *strstr(FileName, " ") = ANSI_NULL;
246
247 /* Load the ramdisk */
248 if (!RamDiskLoadVirtualFile(FileName))
249 {
250 UiMessageBox("Failed to load RAM disk file %s", FileName);
251 return;
252 }
253 }
254
255 TRACE("BootPath: '%s'\n", BootPath);
256
257 /* And check if we booted from floppy */
258 BootFromFloppy = strstr(BootPath, "fdisk") != NULL;
259
260 /* Open 'txtsetup.sif' from any of source paths */
261 File = BootPath + strlen(BootPath);
262 for (i = BootFromFloppy ? 0 : 1; ; i++)
263 {
264 SystemPath = SourcePaths[i];
265 if (!SystemPath)
266 {
267 UiMessageBox("Failed to open txtsetup.sif");
268 return;
269 }
270 strcpy(File, SystemPath);
271 strcpy(FileName, BootPath);
272 strcat(FileName, "txtsetup.sif");
273 if (InfOpenFile(&InfHandle, FileName, &ErrorLine))
274 {
275 break;
276 }
277 }
278
279 TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
280
281 /* Get Load options - debug and non-debug */
282 if (!InfFindFirstLine(InfHandle, "SetupData", "OsLoadOptions", &InfContext))
283 {
284 ERR("Failed to find 'SetupData/OsLoadOptions'\n");
285 return;
286 }
287
288 if (!InfGetDataField(&InfContext, 1, &LoadOptions))
289 {
290 ERR("Failed to get load options\n");
291 return;
292 }
293
294 #if DBG
295 /* Get debug load options and use them */
296 if (InfFindFirstLine(InfHandle, "SetupData", "DbgOsLoadOptions", &InfContext))
297 {
298 LPCSTR DbgLoadOptions;
299
300 if (InfGetDataField(&InfContext, 1, &DbgLoadOptions))
301 LoadOptions = DbgLoadOptions;
302 }
303 #endif
304
305 /* Copy loadoptions (original string will be freed) */
306 BootOptions = FrLdrTempAlloc(strlen(LoadOptions) + 1, TAG_BOOT_OPTIONS);
307 strcpy(BootOptions, LoadOptions);
308
309 TRACE("BootOptions: '%s'\n", BootOptions);
310
311 UiDrawStatusText("Setup is loading...");
312
313 /* Allocate and minimalistic-initialize LPB */
314 AllocateAndInitLPB(&LoaderBlock);
315
316 /* Allocate and initialize setup loader block */
317 SetupBlock = &WinLdrSystemBlock->SetupBlock;
318 LoaderBlock->SetupLdrBlock = SetupBlock;
319
320 /* Set textmode setup flag */
321 SetupBlock->Flags = SETUPLDR_TEXT_MODE;
322
323 /* Load NLS data, they are in system32 */
324 strcpy(FileName, BootPath);
325 strcat(FileName, "system32\\");
326 SetupLdrLoadNlsData(LoaderBlock, InfHandle, FileName);
327
328 /* Get a list of boot drivers */
329 SetupLdrScanBootDrivers(&LoaderBlock->BootDriverListHead, InfHandle, BootPath);
330
331 /* Close the inf file */
332 InfCloseFile(InfHandle);
333
334 /* Load ReactOS Setup */
335 LoadAndBootWindowsCommon(_WIN32_WINNT_WS03,
336 LoaderBlock,
337 BootOptions,
338 BootPath,
339 TRUE);
340 }