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