3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 /* INCLUDES *******************************************************************/
25 DBG_DEFAULT_CHANNEL(INIFILE
);
27 #define TAG_OS_ITEM 'tISO'
29 /* FUNCTIONS ******************************************************************/
31 static PCSTR
CopyString(PCSTR Source
)
38 Dest
= FrLdrHeapAlloc(strlen(Source
) + 1, TAG_STRING
);
46 InitOperatingSystemList(
47 IN ULONG_PTR FrLdrSectionId
,
48 OUT PULONG OperatingSystemCount
,
49 OUT PULONG DefaultOperatingSystem
)
52 PCSTR DefaultOSName
= NULL
;
53 CHAR DefaultOSText
[80];
55 OperatingSystemItem
* Items
;
58 ULONG_PTR OsSectionId
, SectionId
;
59 PCHAR TitleStart
, TitleEnd
;
62 BOOLEAN HadNoBootType
;
63 CHAR SettingName
[260];
64 CHAR SettingValue
[260];
66 CHAR TempBuffer
[sizeof(SettingValue
)/sizeof(CHAR
)];
68 /* Open the [Operating Systems] section */
69 if (!IniOpenSection("Operating Systems", &OsSectionId
))
72 /* Count the number of operating systems in the section */
73 Count
= IniGetNumSectionItems(OsSectionId
);
75 /* Allocate memory to hold operating system lists */
76 Items
= FrLdrHeapAlloc(Count
* sizeof(OperatingSystemItem
), TAG_OS_ITEM
);
80 /* Retrieve which OS is the default one */
81 DefaultOSName
= CmdLineGetDefaultOS();
82 if (!DefaultOSName
|| !*DefaultOSName
)
84 if ((FrLdrSectionId
!= 0) &&
85 IniReadSettingByName(FrLdrSectionId
, "DefaultOS", DefaultOSText
, sizeof(DefaultOSText
)))
87 DefaultOSName
= DefaultOSText
;
91 /* Now loop through the operating system section and load each item */
92 for (i
= 0; i
< Count
; ++i
)
94 IniReadSettingByNumber(OsSectionId
, i
,
95 SettingName
, sizeof(SettingName
),
96 SettingValue
, sizeof(SettingValue
));
99 ERR("Invalid OS entry %lu, skipping.\n", i
);
103 /* Retrieve the start and end of the title */
104 TitleStart
= SettingValue
;
105 /* Trim any leading whitespace and quotes */
106 while (*TitleStart
== ' ' || *TitleStart
== '\t' || *TitleStart
== '"')
108 TitleEnd
= TitleStart
;
109 /* Go up to the first last quote */
110 while (*TitleEnd
!= ANSI_NULL
&& *TitleEnd
!= '"')
113 /* NULL-terminate the title */
115 *TitleEnd
++ = ANSI_NULL
; // Skip the quote too.
117 /* Retrieve the options after the quoted title */
120 /* Trim any trailing whitespace and quotes */
121 while (*TitleEnd
== ' ' || *TitleEnd
== '\t' || *TitleEnd
== '"')
124 OsLoadOptions
= (*TitleEnd
? TitleEnd
: NULL
);
127 // "SettingName = '%s'\n"
128 // "TitleStart = '%s'\n"
129 // "OsLoadOptions = '%s'\n",
130 // SettingName, TitleStart, OsLoadOptions);
132 /* Find the default OS item while we haven't got one */
133 if (DefaultOSName
&& _stricmp(DefaultOSName
, SettingName
) == 0)
136 DefaultOSName
= NULL
; // We have found the first one, don't search for others.
140 * Determine whether this is a legacy operating system entry of the form:
142 * [Operating Systems]
143 * ArcOsLoadPartition="LoadIdentifier" /List /of /Options
145 * and if so, convert it into a new operating system INI entry:
147 * [Operating Systems]
148 * SectionIdentifier="LoadIdentifier"
150 * [SectionIdentifier]
152 * SystemPath=ArcOsLoadPartition
153 * Options=/List /of /Options
155 * The "BootType" value is heuristically determined from the form of
156 * the ArcOsLoadPartition: if this is an ARC path, the "BootType" value
157 * is "Windows", otherwise if this is a DOS path the "BootType" value
158 * is "BootSector". This ensures backwards-compatibility with NTLDR.
161 /* Try to open the operating system section in the .ini file */
163 HadSection
= IniOpenSection(SettingName
, &SectionId
);
166 /* This is a new OS entry: try to read the boot type */
167 IniReadSettingByName(SectionId
, "BootType", BootType
, sizeof(BootType
));
171 /* This is a legacy OS entry: no explicit BootType specified, we will infer one */
172 *BootType
= ANSI_NULL
;
175 /* Check whether we have got a BootType value; if not, try to infer one */
176 HadNoBootType
= (*BootType
== ANSI_NULL
);
181 if (ArcOpen(SettingName
, OpenReadOnly
, &FileId
) == ESUCCESS
)
184 strcpy(BootType
, "BootSector");
189 strcpy(BootType
, "Windows");
193 /* This is a legacy OS entry: convert it into a new OS entry */
198 /* Save the system path from the original SettingName (overwritten below) */
199 RtlStringCbCopyA(TempBuffer
, sizeof(TempBuffer
), SettingName
);
201 /* Generate a unique section name */
202 TimeInfo
= ArcGetTime();
203 if (_stricmp(BootType
, "BootSector") == 0)
205 RtlStringCbPrintfA(SettingName
, sizeof(SettingName
),
206 "BootSectorFile%u%u%u%u%u%u",
207 TimeInfo
->Year
, TimeInfo
->Day
, TimeInfo
->Month
,
208 TimeInfo
->Hour
, TimeInfo
->Minute
, TimeInfo
->Second
);
210 else if (_stricmp(BootType
, "Windows") == 0)
212 RtlStringCbPrintfA(SettingName
, sizeof(SettingName
),
213 "Windows%u%u%u%u%u%u",
214 TimeInfo
->Year
, TimeInfo
->Day
, TimeInfo
->Month
,
215 TimeInfo
->Hour
, TimeInfo
->Minute
, TimeInfo
->Second
);
222 /* Add the section */
223 if (!IniAddSection(SettingName
, &SectionId
))
225 ERR("Could not convert legacy OS entry %lu, skipping.\n", i
);
229 /* Add the system path */
230 if (_stricmp(BootType
, "BootSector") == 0)
232 if (!IniAddSettingValueToSection(SectionId
, "BootSectorFile", TempBuffer
))
234 ERR("Could not convert legacy OS entry %lu, skipping.\n", i
);
238 else if (_stricmp(BootType
, "Windows") == 0)
240 if (!IniAddSettingValueToSection(SectionId
, "SystemPath", TempBuffer
))
242 ERR("Could not convert legacy OS entry %lu, skipping.\n", i
);
251 /* Add the OS options */
252 if (OsLoadOptions
&& !IniAddSettingValueToSection(SectionId
, "Options", OsLoadOptions
))
254 ERR("Could not convert legacy OS entry %lu, skipping.\n", i
);
259 /* Add or modify the BootType if needed */
260 if (HadNoBootType
&& !IniModifySettingValue(SectionId
, "BootType", BootType
))
262 ERR("Could not fixup the BootType entry for OS '%s', ignoring.\n", SettingName
);
266 * If this is a new OS entry, but some options were given appended to
267 * the OS entry item, append them instead to the "Options=" value.
269 if (HadSection
&& OsLoadOptions
&& *OsLoadOptions
)
271 /* Read the original "Options=" value */
272 *TempBuffer
= ANSI_NULL
;
273 if (!IniReadSettingByName(SectionId
, "Options", TempBuffer
, sizeof(TempBuffer
)))
274 TRACE("No 'Options' value found for OS '%s', ignoring.\n", SettingName
);
276 /* Concatenate the options together */
277 RtlStringCbCatA(TempBuffer
, sizeof(TempBuffer
), " ");
278 RtlStringCbCatA(TempBuffer
, sizeof(TempBuffer
), OsLoadOptions
);
281 if (!IniModifySettingValue(SectionId
, "Options", TempBuffer
))
282 ERR("Could not modify the options for OS '%s', ignoring.\n", SettingName
);
285 /* Copy the OS section ID and its identifier */
286 Items
[i
].SectionId
= SectionId
;
287 Items
[i
].LoadIdentifier
= CopyString(TitleStart
);
288 // TRACE("We did Items[%lu]: SectionName = '%s' (SectionId = 0x%p), LoadIdentifier = '%s'\n",
289 // i, SettingName, Items[i].SectionId, Items[i].LoadIdentifier);
293 *OperatingSystemCount
= Count
;
294 *DefaultOperatingSystem
= DefaultOS
;