16a93ed2ea76745a596a9fc18770c7532ea4dc4d
[reactos.git] / reactos / boot / freeldr / freeldr / windows / 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
30 void
31 WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock);
32
33 VOID
34 WinLdrSetProcessorContext(void);
35
36 // TODO: Move to .h
37 VOID AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock);
38
39 static VOID
40 SetupLdrLoadNlsData(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, LPCSTR SearchPath)
41 {
42 INFCONTEXT InfContext;
43 BOOLEAN Status;
44 LPCSTR AnsiName, OemName, LangName;
45
46 /* Get ANSI codepage file */
47 if (!InfFindFirstLine(InfHandle, "NLS", "AnsiCodepage", &InfContext))
48 {
49 ERR("Failed to find 'NLS/AnsiCodepage'\n");
50 return;
51 }
52 if (!InfGetDataField(&InfContext, 1, &AnsiName))
53 {
54 ERR("Failed to get load options\n");
55 return;
56 }
57
58 /* Get OEM codepage file */
59 if (!InfFindFirstLine(InfHandle, "NLS", "OemCodepage", &InfContext))
60 {
61 ERR("Failed to find 'NLS/AnsiCodepage'\n");
62 return;
63 }
64 if (!InfGetDataField(&InfContext, 1, &OemName))
65 {
66 ERR("Failed to get load options\n");
67 return;
68 }
69
70 if (!InfFindFirstLine(InfHandle, "NLS", "UnicodeCasetable", &InfContext))
71 {
72 ERR("Failed to find 'NLS/AnsiCodepage'\n");
73 return;
74 }
75 if (!InfGetDataField(&InfContext, 1, &LangName))
76 {
77 ERR("Failed to get load options\n");
78 return;
79 }
80
81 Status = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
82 TRACE("NLS data loaded with status %d\n", Status);
83 }
84
85 static VOID
86 SetupLdrScanBootDrivers(PLIST_ENTRY BootDriverListHead, HINF InfHandle, LPCSTR SearchPath)
87 {
88 INFCONTEXT InfContext, dirContext;
89 BOOLEAN Status;
90 LPCSTR Media, DriverName, dirIndex, ImagePath;
91 WCHAR ServiceName[256];
92 WCHAR ImagePathW[256];
93
94 /* Open inf section */
95 if (!InfFindFirstLine(InfHandle, "SourceDisksFiles", NULL, &InfContext))
96 return;
97
98 /* Load all listed boot drivers */
99 do
100 {
101 if (InfGetDataField(&InfContext, 7, &Media) &&
102 InfGetDataField(&InfContext, 0, &DriverName) &&
103 InfGetDataField(&InfContext, 13, &dirIndex))
104 {
105 if ((strcmp(Media, "x") == 0) &&
106 InfFindFirstLine(InfHandle, "Directories", dirIndex, &dirContext) &&
107 InfGetDataField(&dirContext, 1, &ImagePath))
108 {
109 /* Convert name to widechar */
110 swprintf(ServiceName, L"%S", DriverName);
111
112 /* Prepare image path */
113 swprintf(ImagePathW, L"%S", ImagePath);
114 wcscat(ImagePathW, L"\\");
115 wcscat(ImagePathW, ServiceName);
116
117 /* Remove .sys extension */
118 ServiceName[wcslen(ServiceName) - 4] = 0;
119
120 /* Add it to the list */
121 Status = WinLdrAddDriverToList(BootDriverListHead,
122 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
123 ImagePathW,
124 ServiceName);
125
126 if (!Status)
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 CHAR FileName[512];
141 CHAR BootPath[512];
142 LPCSTR LoadOptions, BootOptions;
143 BOOLEAN BootFromFloppy;
144 ULONG i, ErrorLine;
145 HINF InfHandle;
146 INFCONTEXT InfContext;
147 PLOADER_PARAMETER_BLOCK LoaderBlock;
148 PSETUP_LOADER_BLOCK SetupBlock;
149 LPCSTR SystemPath;
150 LPCSTR SourcePaths[] =
151 {
152 "\\", /* Only for floppy boot */
153 #if defined(_M_IX86)
154 "\\I386\\",
155 #elif defined(_M_MPPC)
156 "\\PPC\\",
157 #elif defined(_M_MRX000)
158 "\\MIPS\\",
159 #endif
160 "\\reactos\\",
161 NULL
162 };
163
164 /* Get boot path */
165 MachDiskGetBootPath(BootPath, sizeof(BootPath));
166
167 /* And check if we booted from floppy */
168 BootFromFloppy = strstr(BootPath, "fdisk") != NULL;
169
170 /* Open 'txtsetup.sif' from any of source paths */
171 for (i = BootFromFloppy ? 0 : 1; ; i++)
172 {
173 SystemPath = SourcePaths[i];
174 if (!SystemPath)
175 {
176 ERR("Failed to open txtsetup.sif\n");
177 return;
178 }
179 sprintf(FileName, "%stxtsetup.sif", SystemPath);
180 if (InfOpenFile (&InfHandle, FileName, &ErrorLine))
181 {
182 strcat(BootPath, SystemPath);
183 break;
184 }
185 }
186
187 TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
188
189 /* Get Load options - debug and non-debug */
190 if (!InfFindFirstLine(InfHandle, "SetupData", "OsLoadOptions", &InfContext))
191 {
192 ERR("Failed to find 'SetupData/OsLoadOptions'\n");
193 return;
194 }
195
196 if (!InfGetDataField (&InfContext, 1, &LoadOptions))
197 {
198 ERR("Failed to get load options\n");
199 return;
200 }
201
202 BootOptions = LoadOptions;
203
204 #if DBG
205 /* Get debug load options and use them */
206 if (InfFindFirstLine(InfHandle, "SetupData", "DbgOsLoadOptions", &InfContext))
207 {
208 if (InfGetDataField(&InfContext, 1, &LoadOptions))
209 BootOptions = LoadOptions;
210 }
211 #endif
212
213 TRACE("BootOptions: '%s'\n", BootOptions);
214
215 SetupUiInitialize();
216 UiDrawStatusText("Setup is loading...");
217
218 /* Allocate and minimalistic-initialize LPB */
219 AllocateAndInitLPB(&LoaderBlock);
220
221 /* Allocate and initialize setup loader block */
222 SetupBlock = &WinLdrSystemBlock->SetupBlock;
223 LoaderBlock->SetupLdrBlock = SetupBlock;
224
225 /* Set textmode setup flag */
226 SetupBlock->Flags = SETUPLDR_TEXT_MODE;
227
228 /* Load NLS data, they are in system32 */
229 strcpy(FileName, BootPath);
230 strcat(FileName, "system32\\");
231 SetupLdrLoadNlsData(LoaderBlock, InfHandle, FileName);
232
233 /* Get a list of boot drivers */
234 SetupLdrScanBootDrivers(&LoaderBlock->BootDriverListHead, InfHandle, BootPath);
235
236 /* Load ReactOS */
237 LoadAndBootWindowsCommon(_WIN32_WINNT_WS03,
238 LoaderBlock,
239 BootOptions,
240 BootPath,
241 TRUE);
242 }