8f43ac6fe622601b17752ab0b9341d72f8d33a2c
[reactos.git] / freeldr / freeldr / multiboot.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2002 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20
21 #include "freeldr.h"
22 #include "asmcode.h"
23 #include "rtl.h"
24 #include "fs.h"
25 #include "multiboot.h"
26 #include "ui.h"
27 #include "parseini.h"
28
29 unsigned long next_module_load_base = 0;
30 module_t* pOpenModule = NULL;
31
32
33 BOOL MultiBootLoadKernel(FILE *KernelImage)
34 {
35 DWORD ImageHeaders[2048];
36 int Idx;
37 DWORD dwHeaderChecksum;
38 DWORD dwFileLoadOffset;
39 DWORD dwDataSize;
40 DWORD dwBssSize;
41 ULONG BytesRead;
42
43 /*
44 * Load the first 8192 bytes of the kernel image
45 * so we can search for the multiboot header
46 */
47 ReadFile(KernelImage, 8192, NULL, ImageHeaders);
48
49 /*
50 * Now find the multiboot header and copy it
51 */
52 for (Idx=0; Idx<2048; Idx++)
53 {
54 // Did we find it?
55 if (ImageHeaders[Idx] == MULTIBOOT_HEADER_MAGIC)
56 {
57 // Yes, copy it and break out of this loop
58 memcpy(&mb_header, &ImageHeaders[Idx], sizeof(multiboot_header_t));
59
60 break;
61 }
62 }
63
64 /*
65 * If we reached the end of the 8192 bytes without
66 * finding the multiboot header then return error
67 */
68 if (Idx == 2048)
69 {
70 MessageBox("No multiboot header found!");
71 return FALSE;
72 }
73
74 /*printf("multiboot header:\n");
75 printf("0x%x\n", mb_header.magic);
76 printf("0x%x\n", mb_header.flags);
77 printf("0x%x\n", mb_header.checksum);
78 printf("0x%x\n", mb_header.header_addr);
79 printf("0x%x\n", mb_header.load_addr);
80 printf("0x%x\n", mb_header.load_end_addr);
81 printf("0x%x\n", mb_header.bss_end_addr);
82 printf("0x%x\n", mb_header.entry_addr);
83 getch();*/
84
85 /*
86 * Calculate the checksum and make sure it matches
87 */
88 dwHeaderChecksum = mb_header.magic;
89 dwHeaderChecksum += mb_header.flags;
90 dwHeaderChecksum += mb_header.checksum;
91 if (dwHeaderChecksum != 0)
92 {
93 MessageBox("Multiboot header checksum invalid!");
94 return FALSE;
95 }
96
97 /*
98 * Get the file offset, this should be 0, and move the file pointer
99 */
100 dwFileLoadOffset = (Idx * sizeof(DWORD)) - (mb_header.header_addr - mb_header.load_addr);
101 SetFilePointer(KernelImage, dwFileLoadOffset);
102
103 /*
104 * Load the file image
105 */
106 dwDataSize = (mb_header.load_end_addr - mb_header.load_addr);
107 ReadFile(KernelImage, dwDataSize, NULL, (void*)mb_header.load_addr);
108
109 /*
110 * Initialize bss area
111 */
112 dwBssSize = (mb_header.bss_end_addr - mb_header.load_end_addr);
113 memset((void*)mb_header.load_end_addr, 0, dwBssSize);
114
115 next_module_load_base = ROUND_UP(mb_header.bss_end_addr, /*PAGE_SIZE*/4096);
116
117 return TRUE;
118 }
119
120 #if 0
121 BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName)
122 {
123 DWORD dwModuleSize;
124 module_t* pModule;
125 char* ModuleNameString;
126 char * TempName;
127
128 /*
129 * Get current module data structure and module name string array
130 */
131 pModule = &multiboot_modules[mb_info.mods_count];
132 do {
133 TempName = strchr( ModuleName, '\\' );
134 if( TempName )
135 ModuleName = TempName + 1;
136 } while( TempName );
137
138 ModuleNameString = multiboot_module_strings[mb_info.mods_count];
139
140 dwModuleSize = GetFileSize(ModuleImage);
141 pModule->mod_start = next_module_load_base;
142 pModule->mod_end = next_module_load_base + dwModuleSize;
143 strcpy(ModuleNameString, ModuleName);
144 pModule->string = (unsigned long)ModuleNameString;
145
146 /*
147 * Load the file image
148 */
149 ReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base);
150
151 next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096);
152 mb_info.mods_count++;
153
154 return TRUE;
155 }
156 #endif
157
158 PVOID MultiBootLoadModule(FILE *ModuleImage, char *ModuleName, PULONG ModuleSize)
159 {
160 DWORD dwModuleSize;
161 module_t* pModule;
162 char* ModuleNameString;
163 char * TempName;
164
165 /*
166 * Get current module data structure and module name string array
167 */
168 pModule = &multiboot_modules[mb_info.mods_count];
169 do {
170 TempName = strchr( ModuleName, '\\' );
171 if( TempName )
172 ModuleName = TempName + 1;
173 } while( TempName );
174
175 ModuleNameString = multiboot_module_strings[mb_info.mods_count];
176
177 dwModuleSize = GetFileSize(ModuleImage);
178 pModule->mod_start = next_module_load_base;
179 pModule->mod_end = next_module_load_base + dwModuleSize;
180 strcpy(ModuleNameString, ModuleName);
181 pModule->string = (unsigned long)ModuleNameString;
182
183 /*
184 * Load the file image
185 */
186 ReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base);
187
188 next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096);
189 mb_info.mods_count++;
190
191 if (ModuleSize != NULL)
192 *ModuleSize = dwModuleSize;
193
194 return((PVOID)pModule->mod_start);
195 }
196
197 int GetBootPartition(char *OperatingSystemName)
198 {
199 int BootPartitionNumber = -1;
200 char value[1024];
201 ULONG SectionId;
202
203 if (OpenSection(OperatingSystemName, &SectionId))
204 {
205 if (ReadSectionSettingByName(SectionId, "BootPartition", value, 1024))
206 {
207 BootPartitionNumber = atoi(value);
208 }
209 }
210
211 return BootPartitionNumber;
212 }
213
214
215 PVOID MultiBootCreateModule(char *ModuleName)
216 {
217 module_t* pModule;
218 char* ModuleNameString;
219
220 /*
221 * Get current module data structure and module name string array
222 */
223 pModule = &multiboot_modules[mb_info.mods_count];
224
225 ModuleNameString = multiboot_module_strings[mb_info.mods_count];
226
227 pModule->mod_start = next_module_load_base;
228 pModule->mod_end = -1;
229 strcpy(ModuleNameString, ModuleName);
230 pModule->string = (unsigned long)ModuleNameString;
231
232 pOpenModule = pModule;
233
234 return((PVOID)pModule->mod_start);
235 }
236
237
238 BOOL MultiBootCloseModule(PVOID ModuleBase, DWORD dwModuleSize)
239 {
240 module_t* pModule;
241
242 if ((pOpenModule != NULL) &&
243 ((module_t*)ModuleBase == pOpenModule->mod_start) &&
244 (pOpenModule->mod_end == -1))
245 {
246 pModule = pOpenModule;
247 pModule->mod_end = pModule->mod_start + dwModuleSize;
248
249 next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096);
250 mb_info.mods_count++;
251 pOpenModule = NULL;
252
253 return(TRUE);
254 }
255
256 return(FALSE);
257 }