[FREELDR] Re-integrate the ASM files (and corresponding C code) in MSVC builds, that...
[reactos.git] / boot / freeldr / freeldr / arch / i386 / drivemap.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 *
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.
9 *
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.
14 *
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.
18 */
19
20 #include <freeldr.h>
21 #include <debug.h>
22
23 DBG_DEFAULT_CHANNEL(DISK);
24
25 BOOLEAN DriveMapInstalled = FALSE; // Tells us if we have already installed our drive map int 13h handler code
26 ULONG OldInt13HandlerAddress = 0; // Address of BIOS int 13h handler
27 ULONG DriveMapHandlerAddress = 0; // Linear address of our drive map handler
28 ULONG DriveMapHandlerSegOff = 0; // Segment:offset style address of our drive map handler
29
30 VOID DriveMapMapDrivesInSection(PCSTR SectionName)
31 {
32 CHAR SettingName[80];
33 CHAR SettingValue[80];
34 CHAR Drive1[80];
35 CHAR Drive2[80];
36 ULONG_PTR SectionId;
37 ULONG SectionItemCount;
38 ULONG Index;
39 ULONG Index2;
40 DRIVE_MAP_LIST DriveMapList;
41
42 RtlZeroMemory(&DriveMapList, sizeof(DRIVE_MAP_LIST));
43
44 if (!IniOpenSection(SectionName, &SectionId))
45 {
46 return;
47 }
48
49 // Get the number of items in this section
50 SectionItemCount = IniGetNumSectionItems(SectionId);
51
52 // Loop through each one and check if its a DriveMap= setting
53 for (Index=0; Index<SectionItemCount; Index++)
54 {
55 // Get the next setting from the .ini file section
56 if (IniReadSettingByNumber(SectionId, Index, SettingName, sizeof(SettingName), SettingValue, sizeof(SettingValue)))
57 {
58 if (_stricmp(SettingName, "DriveMap") == 0)
59 {
60 // Make sure we haven't exceeded the drive map max count
61 if (DriveMapList.DriveMapCount >= 4)
62 {
63 UiMessageBox("Max DriveMap count exceeded in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue);
64 continue;
65 }
66
67 RtlZeroMemory(Drive1, 80);
68 RtlZeroMemory(Drive2, 80);
69
70 strcpy(Drive1, SettingValue);
71
72 // Parse the setting value and separate a string "hd0,hd1"
73 // into two strings "hd0" and "hd1"
74 for (Index2=0; Index2<strlen(Drive1); Index2++)
75 {
76 // Check if this character is the separater character (comma - ',')
77 if (Drive1[Index2] == ',')
78 {
79 Drive1[Index2] = '\0';
80 strcpy(Drive2, &Drive1[Index2+1]);
81 break;
82 }
83 }
84
85 // Make sure we got good values before we add them to the map
86 if (!DriveMapIsValidDriveString(Drive1) || !DriveMapIsValidDriveString(Drive2))
87 {
88 UiMessageBox("Error in DriveMap setting in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue);
89 continue;
90 }
91
92 // Add them to the map
93 DriveMapList.DriveMap[(DriveMapList.DriveMapCount * 2)] = DriveMapGetBiosDriveNumber(Drive1);
94 DriveMapList.DriveMap[(DriveMapList.DriveMapCount * 2)+1] = DriveMapGetBiosDriveNumber(Drive2);
95 DriveMapList.DriveMapCount++;
96
97 TRACE("Mapping BIOS drive 0x%x to drive 0x%x\n", DriveMapGetBiosDriveNumber(Drive1), DriveMapGetBiosDriveNumber(Drive2));
98 }
99 }
100 }
101
102 if (DriveMapList.DriveMapCount)
103 {
104 TRACE("Installing Int13 drive map for %d drives.\n", DriveMapList.DriveMapCount);
105 DriveMapInstallInt13Handler(&DriveMapList);
106 }
107 else
108 {
109 TRACE("Removing any previously installed Int13 drive map.\n");
110 DriveMapRemoveInt13Handler();
111 }
112 }
113
114 BOOLEAN DriveMapIsValidDriveString(PCSTR DriveString)
115 {
116 ULONG Index;
117
118 // Now verify that the user has given us appropriate strings
119 if ((strlen(DriveString) < 3) ||
120 ((DriveString[0] != 'f') && (DriveString[0] != 'F') &&
121 (DriveString[0] != 'h') && (DriveString[0] != 'H')) ||
122 ((DriveString[1] != 'd') && (DriveString[1] != 'D')))
123 {
124 return FALSE;
125 }
126
127 // Now verify that the user has given us appropriate numbers
128 // Make sure that only numeric characters were given
129 for (Index = 2; Index < strlen(DriveString); Index++)
130 {
131 if (DriveString[Index] < '0' || DriveString[Index] > '9')
132 {
133 return FALSE;
134 }
135 }
136
137 // Now make sure that they are not outrageous values (i.e. hd90874)
138 if ((atoi(&DriveString[2]) < 0) || (atoi(&DriveString[2]) > 0xff))
139 {
140 return FALSE;
141 }
142
143 return TRUE;
144 }
145
146 UCHAR DriveMapGetBiosDriveNumber(PCSTR DeviceName)
147 {
148 UCHAR BiosDriveNumber = 0;
149
150 TRACE("DriveMapGetBiosDriveNumber(%s)\n", DeviceName);
151
152 // If they passed in a number string then just
153 // convert it to decimal and return it
154 if (DeviceName[0] >= '0' && DeviceName[0] <= '9')
155 {
156 return (UCHAR)strtoul(DeviceName, NULL, 0);
157 }
158
159 // Convert the drive number string into a number
160 // 'hd1' = 1
161 BiosDriveNumber = atoi(&DeviceName[2]);
162
163 // If it's a hard disk then set the high bit
164 if ((DeviceName[0] == 'h' || DeviceName[0] == 'H') &&
165 (DeviceName[1] == 'd' || DeviceName[1] == 'D'))
166 {
167 BiosDriveNumber |= 0x80;
168 }
169
170 return BiosDriveNumber;
171 }
172
173 VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap)
174 {
175 ULONG* RealModeIVT = (ULONG*)0x00000000;
176 USHORT* BiosLowMemorySize = (USHORT*)0x00000413;
177
178 if (!DriveMapInstalled)
179 {
180 // Get the old INT 13h handler address from the vector table
181 OldInt13HandlerAddress = RealModeIVT[0x13];
182
183 // Decrease the size of low memory
184 (*BiosLowMemorySize)--;
185
186 // Get linear address for drive map handler
187 DriveMapHandlerAddress = (ULONG)(*BiosLowMemorySize) << 10;
188
189 // Convert to segment:offset style address
190 DriveMapHandlerSegOff = (DriveMapHandlerAddress << 12) & 0xffff0000;
191 }
192
193 // Copy the drive map structure to the proper place
194 RtlCopyMemory(&DriveMapInt13HandlerMapList, DriveMap, sizeof(DRIVE_MAP_LIST));
195
196 // Set the address of the BIOS INT 13h handler
197 DriveMapOldInt13HandlerAddress = OldInt13HandlerAddress;
198
199 // Copy the code to our reserved area
200 RtlCopyMemory((PVOID)DriveMapHandlerAddress, &DriveMapInt13HandlerStart, ((ULONG)&DriveMapInt13HandlerEnd - (ULONG)&DriveMapInt13HandlerStart));
201
202 // Update the IVT
203 RealModeIVT[0x13] = DriveMapHandlerSegOff;
204
205 CacheInvalidateCacheData();
206 DriveMapInstalled = TRUE;
207 }
208
209 VOID DriveMapRemoveInt13Handler(VOID)
210 {
211 ULONG* RealModeIVT = (ULONG*)0x00000000;
212 USHORT* BiosLowMemorySize = (USHORT*)0x00000413;
213
214 if (DriveMapInstalled)
215 {
216 // Get the old INT 13h handler address from the vector table
217 RealModeIVT[0x13] = OldInt13HandlerAddress;
218
219 // Increase the size of low memory
220 (*BiosLowMemorySize)++;
221
222 CacheInvalidateCacheData();
223 DriveMapInstalled = FALSE;
224 }
225 }