1 /*
2 * PROJECT: FreeLoader
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * or MIT (https://spdx.org/licenses/MIT)
5 * PURPOSE: Command-line parsing and global settings management
6 * COPYRIGHT: Copyright 2008-2010 ReactOS Portable Systems Group <ros.arm@reactos.org>
7 * Copyright 2015-2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <freeldr.h>
13
14 /* GLOBALS ********************************************************************/
15
16 static CCHAR DebugString[256];
17 static CCHAR DefaultOs[256];
18 BOOTMGRINFO BootMgrInfo = {NULL, NULL, -1, 0};
19
20 /* FUNCTIONS ******************************************************************/
21
22 static VOID
CmdLineParse(_In_ PCSTR CmdLine)23 CmdLineParse(
24 _In_ PCSTR CmdLine)
25 {
26 PCHAR End, Setting;
27 ULONG_PTR Length, Offset = 0;
28
29 /*
30 * Get the debug string, in the following format:
31 * "debug=option1=XXX;option2=YYY;..."
32 * and translate it into the format:
33 * "OPTION1=XXX OPTION2=YYY ..."
34 */
35 Setting = strstr(CmdLine, "debug=");
36 if (Setting)
37 {
38 /* Check if there are more command-line parameters following */
39 Setting += sizeof("debug=") - sizeof(ANSI_NULL);
40 End = strstr(Setting, " ");
41 Length = (End ? (End - Setting) : strlen(Setting));
42
43 /* Copy the debug string and upcase it */
44 RtlStringCbCopyNA(DebugString, sizeof(DebugString), Setting, Length);
45 _strupr(DebugString);
46
47 /* Replace all separators ';' by spaces */
48 Setting = DebugString;
49 while (*Setting)
50 {
51 if (*Setting == ';') *Setting = ' ';
52 Setting++;
53 }
54
55 BootMgrInfo.DebugString = DebugString;
56 }
57
58 /* Get the timeout */
59 Setting = strstr(CmdLine, "timeout=");
60 if (Setting)
61 {
62 BootMgrInfo.TimeOut = atoi(Setting +
63 sizeof("timeout=") - sizeof(ANSI_NULL));
64 }
65
66 /* Get the default OS */
67 Setting = strstr(CmdLine, "defaultos=");
68 if (Setting)
69 {
70 /* Check if there are more command-line parameters following */
71 Setting += sizeof("defaultos=") - sizeof(ANSI_NULL);
72 End = strstr(Setting, " ");
73 Length = (End ? (End - Setting) : strlen(Setting));
74
75 /* Copy the default OS */
76 RtlStringCbCopyNA(DefaultOs, sizeof(DefaultOs), Setting, Length);
77 BootMgrInfo.DefaultOs = DefaultOs;
78 }
79
80 /* Get the ramdisk base address */
81 Setting = strstr(CmdLine, "rdbase=");
82 if (Setting)
83 {
84 gInitRamDiskBase =
85 (PVOID)(ULONG_PTR)strtoull(Setting +
86 sizeof("rdbase=") - sizeof(ANSI_NULL),
87 NULL, 0);
88 }
89
90 /* Get the ramdisk size */
91 Setting = strstr(CmdLine, "rdsize=");
92 if (Setting)
93 {
94 gInitRamDiskSize = strtoul(Setting +
95 sizeof("rdsize=") - sizeof(ANSI_NULL),
96 NULL, 0);
97 }
98
99 /* Get the ramdisk offset */
100 Setting = strstr(CmdLine, "rdoffset=");
101 if (Setting)
102 {
103 Offset = strtoul(Setting +
104 sizeof("rdoffset=") - sizeof(ANSI_NULL),
105 NULL, 0);
106 }
107
108 /* Fix it up */
109 gInitRamDiskBase = (PVOID)((ULONG_PTR)gInitRamDiskBase + Offset);
110 }
111
112 VOID
LoadSettings(_In_opt_ PCSTR CmdLine)113 LoadSettings(
114 _In_opt_ PCSTR CmdLine)
115 {
116 /* Pre-initialization: The settings originate from the command-line.
117 * Main initialization: Overwrite them if needed with those from freeldr.ini */
118 if (CmdLine)
119 {
120 CmdLineParse(CmdLine);
121 return;
122 }
123 else if (IsListEmpty(&IniFileSectionListHead))
124 {
125 // ERR("LoadSettings() called but no freeldr.ini\n");
126 return;
127 }
128
129 BOOLEAN FoundLoaderSection = FALSE;
130 PCSTR LoaderSections[] = {
131 "FreeLoader",
132 "Boot Loader",
133 "FlexBoot",
134 "MultiBoot",
135 };
136
137 /* Search for the first section in LoaderSections and load the settings,
138 * prioritizing the order in the file.
139 * If a section is already loaded, skip further checks. */
140 if (!BootMgrInfo.FrLdrSection)
141 {
142 for (ULONG i = 0; i < sizeof(LoaderSections) / sizeof(LoaderSections[0]); i++)
143 {
144 PCSTR Section = LoaderSections[i];
145
146 if (IniOpenSection(Section, &BootMgrInfo.FrLdrSection))
147 {
148 FoundLoaderSection = TRUE;
149 break;
150 }
151 }
152
153 if (!FoundLoaderSection)
154 {
155 UiMessageBoxCritical("Bootloader Section not found in freeldr.ini");
156 return;
157 }
158 }
159
160 /* Get the debug string. Always override it with the one from freeldr.ini */
161 if (IniReadSettingByName(BootMgrInfo.FrLdrSection, "Debug",
162 DebugString, sizeof(DebugString)))
163 {
164 BootMgrInfo.DebugString = DebugString;
165 }
166
167 /* Get the timeout. Keep the existing one if it is valid,
168 * otherwise retrieve it from freeldr.ini */
169 if (BootMgrInfo.TimeOut < 0)
170 {
171 CHAR TimeOutText[20];
172 BootMgrInfo.TimeOut = -1;
173 if (IniReadSettingByName(BootMgrInfo.FrLdrSection, "TimeOut",
174 TimeOutText, sizeof(TimeOutText)))
175 {
176 BootMgrInfo.TimeOut = atoi(TimeOutText);
177 }
178 }
179
180 /* Get the default OS */
181 if (!BootMgrInfo.DefaultOs || !*BootMgrInfo.DefaultOs)
182 {
183 if (IniReadSettingByName(BootMgrInfo.FrLdrSection, "DefaultOS",
184 DefaultOs, sizeof(DefaultOs)))
185 {
186 BootMgrInfo.DefaultOs = DefaultOs;
187 }
188 }
189 }
190
191 /* EOF */
192