Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlinuxboot.c
Go to the documentation of this file.
00001 /* 00002 * FreeLoader 00003 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 00020 #ifndef _M_ARM 00021 00022 #include <freeldr.h> 00023 #include <debug.h> 00024 #ifdef __i386__ 00025 #define LINUX_READ_CHUNK_SIZE 0x20000 // Read 128k at a time 00026 00027 DBG_DEFAULT_CHANNEL(LINUX); 00028 00029 PLINUX_BOOTSECTOR LinuxBootSector = NULL; 00030 PLINUX_SETUPSECTOR LinuxSetupSector = NULL; 00031 ULONG SetupSectorSize = 0; 00032 BOOLEAN NewStyleLinuxKernel = FALSE; 00033 ULONG LinuxKernelSize = 0; 00034 ULONG LinuxInitrdSize = 0; 00035 CHAR LinuxKernelName[260]; 00036 CHAR LinuxInitrdName[260]; 00037 BOOLEAN LinuxHasInitrd = FALSE; 00038 CHAR LinuxCommandLine[260] = ""; 00039 ULONG LinuxCommandLineSize = 0; 00040 PVOID LinuxKernelLoadAddress = NULL; 00041 PVOID LinuxInitrdLoadAddress = NULL; 00042 CHAR LinuxBootDescription[80]; 00043 CHAR LinuxBootPath[260] = ""; 00044 00045 BOOLEAN RemoveQuotes(PCHAR QuotedString) 00046 { 00047 CHAR TempString[200]; 00048 PCHAR p; 00049 PSTR Start; 00050 00051 // 00052 // Skip spaces up to " 00053 // 00054 p = QuotedString; 00055 while (*p == ' ' || *p == '"') 00056 p++; 00057 Start = p; 00058 00059 // 00060 // Go up to next " 00061 // 00062 while (*p != '"' && *p != ANSI_NULL) 00063 p++; 00064 *p = ANSI_NULL; 00065 00066 // 00067 // Copy result 00068 // 00069 strcpy(TempString, Start); 00070 strcpy(QuotedString, TempString); 00071 00072 return TRUE; 00073 } 00074 00075 VOID LoadAndBootLinux(PCSTR OperatingSystemName, PCSTR Description) 00076 { 00077 PFILE LinuxKernel = 0; 00078 PFILE LinuxInitrdFile = 0; 00079 CHAR TempString[260]; 00080 00081 UiDrawBackdrop(); 00082 00083 if (Description) 00084 { 00085 sprintf(LinuxBootDescription, "Loading %s...", Description); 00086 } 00087 else 00088 { 00089 strcpy(LinuxBootDescription, "Loading Linux..."); 00090 } 00091 00092 UiDrawStatusText(LinuxBootDescription); 00093 UiDrawProgressBarCenter(0, 100, LinuxBootDescription); 00094 00095 // Parse the .ini file section 00096 if (!LinuxParseIniSection(OperatingSystemName)) 00097 { 00098 goto LinuxBootFailed; 00099 } 00100 00101 // Open the kernel 00102 LinuxKernel = FsOpenFile(LinuxKernelName); 00103 if (!LinuxKernel) 00104 { 00105 sprintf(TempString, "Linux kernel \'%s\' not found.", LinuxKernelName); 00106 UiMessageBox(TempString); 00107 goto LinuxBootFailed; 00108 } 00109 00110 // Open the initrd file image (if necessary) 00111 if (LinuxHasInitrd) 00112 { 00113 LinuxInitrdFile = FsOpenFile(LinuxInitrdName); 00114 if (!LinuxInitrdFile) 00115 { 00116 sprintf(TempString, "Linux initrd image \'%s\' not found.", LinuxInitrdName); 00117 UiMessageBox(TempString); 00118 goto LinuxBootFailed; 00119 } 00120 } 00121 00122 // Read the boot sector 00123 if (!LinuxReadBootSector(LinuxKernel)) 00124 { 00125 goto LinuxBootFailed; 00126 } 00127 00128 // Read the setup sector 00129 if (!LinuxReadSetupSector(LinuxKernel)) 00130 { 00131 goto LinuxBootFailed; 00132 } 00133 00134 // Calc kernel size 00135 LinuxKernelSize = FsGetFileSize(LinuxKernel) - (512 + SetupSectorSize); 00136 00137 // Get the file size 00138 LinuxInitrdSize = FsGetFileSize(LinuxInitrdFile); 00139 00140 // Read the kernel 00141 if (!LinuxReadKernel(LinuxKernel)) 00142 { 00143 goto LinuxBootFailed; 00144 } 00145 00146 // Read the initrd (if necessary) 00147 if (LinuxHasInitrd) 00148 { 00149 if (!LinuxReadInitrd(LinuxInitrdFile)) 00150 { 00151 goto LinuxBootFailed; 00152 } 00153 } 00154 00155 // If the default root device is set to FLOPPY (0000h), change to /dev/fd0 (0200h) 00156 if (LinuxBootSector->RootDevice == 0x0000) 00157 { 00158 LinuxBootSector->RootDevice = 0x0200; 00159 } 00160 00161 if (LinuxSetupSector->Version >= 0x0202) 00162 { 00163 LinuxSetupSector->CommandLinePointer = 0x99000; 00164 } 00165 else 00166 { 00167 LinuxBootSector->CommandLineMagic = LINUX_COMMAND_LINE_MAGIC; 00168 LinuxBootSector->CommandLineOffset = 0x9000; 00169 } 00170 00171 if (NewStyleLinuxKernel) 00172 { 00173 LinuxSetupSector->TypeOfLoader = LINUX_LOADER_TYPE_FREELOADER; 00174 } 00175 else 00176 { 00177 LinuxSetupSector->LoadFlags = 0; 00178 } 00179 00180 RtlCopyMemory((PVOID)0x90000, LinuxBootSector, 512); 00181 RtlCopyMemory((PVOID)0x90200, LinuxSetupSector, SetupSectorSize); 00182 RtlCopyMemory((PVOID)0x99000, LinuxCommandLine, LinuxCommandLineSize); 00183 00184 UiUnInitialize("Booting Linux..."); 00185 00186 DiskStopFloppyMotor(); 00187 00188 if (LinuxSetupSector->LoadFlags & LINUX_FLAG_LOAD_HIGH) 00189 { 00190 BootNewLinuxKernel(); 00191 } 00192 else 00193 { 00194 BootOldLinuxKernel(LinuxKernelSize); 00195 } 00196 00197 00198 LinuxBootFailed: 00199 00200 if (LinuxKernel) 00201 { 00202 FsCloseFile(LinuxKernel); 00203 } 00204 if (LinuxInitrdFile) 00205 { 00206 FsCloseFile(LinuxInitrdFile); 00207 } 00208 00209 if (LinuxBootSector != NULL) 00210 { 00211 MmFreeMemory(LinuxBootSector); 00212 } 00213 if (LinuxSetupSector != NULL) 00214 { 00215 MmFreeMemory(LinuxSetupSector); 00216 } 00217 if (LinuxKernelLoadAddress != NULL) 00218 { 00219 MmFreeMemory(LinuxKernelLoadAddress); 00220 } 00221 if (LinuxInitrdLoadAddress != NULL) 00222 { 00223 MmFreeMemory(LinuxInitrdLoadAddress); 00224 } 00225 00226 LinuxBootSector = NULL; 00227 LinuxSetupSector = NULL; 00228 LinuxKernelLoadAddress = NULL; 00229 LinuxInitrdLoadAddress = NULL; 00230 SetupSectorSize = 0; 00231 NewStyleLinuxKernel = FALSE; 00232 LinuxKernelSize = 0; 00233 LinuxHasInitrd = FALSE; 00234 strcpy(LinuxCommandLine, ""); 00235 LinuxCommandLineSize = 0; 00236 } 00237 00238 BOOLEAN LinuxParseIniSection(PCSTR OperatingSystemName) 00239 { 00240 CHAR SettingName[260]; 00241 ULONG SectionId; 00242 00243 // Find all the message box settings and run them 00244 UiShowMessageBoxesInSection(OperatingSystemName); 00245 00246 // Try to open the operating system section in the .ini file 00247 if (!IniOpenSection(OperatingSystemName, &SectionId)) 00248 { 00249 sprintf(SettingName, "Section [%s] not found in freeldr.ini.\n", OperatingSystemName); 00250 UiMessageBox(SettingName); 00251 return FALSE; 00252 } 00253 00254 if (!IniReadSettingByName(SectionId, "BootPath", LinuxBootPath, sizeof(LinuxBootPath))) 00255 { 00256 UiMessageBox("Boot path not specified for selected OS!"); 00257 return FALSE; 00258 } 00259 00260 // Get the kernel name 00261 if (!IniReadSettingByName(SectionId, "Kernel", LinuxKernelName, sizeof(LinuxKernelName))) 00262 { 00263 UiMessageBox("Linux kernel filename not specified for selected OS!"); 00264 return FALSE; 00265 } 00266 00267 // Get the initrd name 00268 if (IniReadSettingByName(SectionId, "Initrd", LinuxInitrdName, sizeof(LinuxInitrdName))) 00269 { 00270 LinuxHasInitrd = TRUE; 00271 } 00272 00273 // Get the command line 00274 if (IniReadSettingByName(SectionId, "CommandLine", LinuxCommandLine, sizeof(LinuxCommandLine))) 00275 { 00276 RemoveQuotes(LinuxCommandLine); 00277 LinuxCommandLineSize = strlen(LinuxCommandLine) + 1; 00278 } 00279 00280 return TRUE; 00281 } 00282 00283 BOOLEAN LinuxReadBootSector(PFILE LinuxKernelFile) 00284 { 00285 // Allocate memory for boot sector 00286 LinuxBootSector = MmAllocateMemoryWithType(512, LoaderSystemCode); 00287 if (LinuxBootSector == NULL) 00288 { 00289 return FALSE; 00290 } 00291 00292 // Read linux boot sector 00293 FsSetFilePointer(LinuxKernelFile, 0); 00294 if (!FsReadFile(LinuxKernelFile, 512, NULL, LinuxBootSector)) 00295 { 00296 return FALSE; 00297 } 00298 00299 // Check for validity 00300 if (LinuxBootSector->BootFlag != LINUX_BOOT_SECTOR_MAGIC) 00301 { 00302 UiMessageBox("Invalid boot sector magic (0xaa55)"); 00303 return FALSE; 00304 } 00305 00306 DbgDumpBuffer(DPRINT_LINUX, LinuxBootSector, 512); 00307 00308 TRACE("SetupSectors: %d\n", LinuxBootSector->SetupSectors); 00309 TRACE("RootFlags: 0x%x\n", LinuxBootSector->RootFlags); 00310 TRACE("SystemSize: 0x%x\n", LinuxBootSector->SystemSize); 00311 TRACE("SwapDevice: 0x%x\n", LinuxBootSector->SwapDevice); 00312 TRACE("RamSize: 0x%x\n", LinuxBootSector->RamSize); 00313 TRACE("VideoMode: 0x%x\n", LinuxBootSector->VideoMode); 00314 TRACE("RootDevice: 0x%x\n", LinuxBootSector->RootDevice); 00315 TRACE("BootFlag: 0x%x\n", LinuxBootSector->BootFlag); 00316 00317 return TRUE; 00318 } 00319 00320 BOOLEAN LinuxReadSetupSector(PFILE LinuxKernelFile) 00321 { 00322 UCHAR TempLinuxSetupSector[512]; 00323 00324 LinuxSetupSector = (PLINUX_SETUPSECTOR)TempLinuxSetupSector; 00325 00326 // Read first linux setup sector 00327 FsSetFilePointer(LinuxKernelFile, 512); 00328 if (!FsReadFile(LinuxKernelFile, 512, NULL, TempLinuxSetupSector)) 00329 { 00330 return FALSE; 00331 } 00332 00333 // Check the kernel version 00334 if (!LinuxCheckKernelVersion()) 00335 { 00336 return FALSE; 00337 } 00338 00339 if (NewStyleLinuxKernel) 00340 { 00341 SetupSectorSize = 512 * LinuxBootSector->SetupSectors; 00342 } 00343 else 00344 { 00345 SetupSectorSize = 4 * 512; // Always 4 setup sectors 00346 } 00347 00348 // Allocate memory for setup sectors 00349 LinuxSetupSector = MmAllocateMemoryWithType(SetupSectorSize, LoaderSystemCode); 00350 if (LinuxSetupSector == NULL) 00351 { 00352 return FALSE; 00353 } 00354 00355 // Copy over first setup sector 00356 RtlCopyMemory(LinuxSetupSector, TempLinuxSetupSector, 512); 00357 00358 // Read in the rest of the linux setup sectors 00359 FsSetFilePointer(LinuxKernelFile, 1024); 00360 if (!FsReadFile(LinuxKernelFile, SetupSectorSize - 512, NULL, (PVOID)((ULONG_PTR)LinuxSetupSector + 512))) 00361 { 00362 return FALSE; 00363 } 00364 00365 DbgDumpBuffer(DPRINT_LINUX, LinuxSetupSector, SetupSectorSize); 00366 00367 TRACE("SetupHeaderSignature: 0x%x (HdrS)\n", LinuxSetupSector->SetupHeaderSignature); 00368 TRACE("Version: 0x%x\n", LinuxSetupSector->Version); 00369 TRACE("RealModeSwitch: 0x%x\n", LinuxSetupSector->RealModeSwitch); 00370 TRACE("SetupSeg: 0x%x\n", LinuxSetupSector->SetupSeg); 00371 TRACE("StartSystemSeg: 0x%x\n", LinuxSetupSector->StartSystemSeg); 00372 TRACE("KernelVersion: 0x%x\n", LinuxSetupSector->KernelVersion); 00373 TRACE("TypeOfLoader: 0x%x\n", LinuxSetupSector->TypeOfLoader); 00374 TRACE("LoadFlags: 0x%x\n", LinuxSetupSector->LoadFlags); 00375 TRACE("SetupMoveSize: 0x%x\n", LinuxSetupSector->SetupMoveSize); 00376 TRACE("Code32Start: 0x%x\n", LinuxSetupSector->Code32Start); 00377 TRACE("RamdiskAddress: 0x%x\n", LinuxSetupSector->RamdiskAddress); 00378 TRACE("RamdiskSize: 0x%x\n", LinuxSetupSector->RamdiskSize); 00379 TRACE("BootSectKludgeOffset: 0x%x\n", LinuxSetupSector->BootSectKludgeOffset); 00380 TRACE("BootSectKludgeSegment: 0x%x\n", LinuxSetupSector->BootSectKludgeSegment); 00381 TRACE("HeapEnd: 0x%x\n", LinuxSetupSector->HeapEnd); 00382 00383 return TRUE; 00384 } 00385 00386 BOOLEAN LinuxReadKernel(PFILE LinuxKernelFile) 00387 { 00388 ULONG BytesLoaded; 00389 CHAR StatusText[260]; 00390 PVOID LoadAddress; 00391 00392 sprintf(StatusText, "Loading %s", LinuxKernelName); 00393 UiDrawStatusText(StatusText); 00394 00395 // Allocate memory for Linux kernel 00396 LinuxKernelLoadAddress = MmAllocateMemoryAtAddress(LinuxKernelSize, (PVOID)LINUX_KERNEL_LOAD_ADDRESS, LoaderSystemCode); 00397 if (LinuxKernelLoadAddress != (PVOID)LINUX_KERNEL_LOAD_ADDRESS) 00398 { 00399 return FALSE; 00400 } 00401 00402 LoadAddress = LinuxKernelLoadAddress; 00403 00404 // Read linux kernel to 0x100000 (1mb) 00405 FsSetFilePointer(LinuxKernelFile, 512 + SetupSectorSize); 00406 for (BytesLoaded=0; BytesLoaded<LinuxKernelSize; ) 00407 { 00408 if (!FsReadFile(LinuxKernelFile, LINUX_READ_CHUNK_SIZE, NULL, LoadAddress)) 00409 { 00410 return FALSE; 00411 } 00412 00413 BytesLoaded += LINUX_READ_CHUNK_SIZE; 00414 LoadAddress = (PVOID)((ULONG_PTR)LoadAddress + LINUX_READ_CHUNK_SIZE); 00415 00416 UiDrawProgressBarCenter(BytesLoaded, LinuxKernelSize + LinuxInitrdSize, LinuxBootDescription); 00417 } 00418 00419 return TRUE; 00420 } 00421 00422 BOOLEAN LinuxCheckKernelVersion(VOID) 00423 { 00424 // Just assume old kernel until we find otherwise 00425 NewStyleLinuxKernel = FALSE; 00426 00427 // Check for new style setup header 00428 if (LinuxSetupSector->SetupHeaderSignature != LINUX_SETUP_HEADER_ID) 00429 { 00430 NewStyleLinuxKernel = FALSE; 00431 } 00432 // Check for version below 2.0 00433 else if (LinuxSetupSector->Version < 0x0200) 00434 { 00435 NewStyleLinuxKernel = FALSE; 00436 } 00437 // Check for version 2.0 00438 else if (LinuxSetupSector->Version == 0x0200) 00439 { 00440 NewStyleLinuxKernel = TRUE; 00441 } 00442 // Check for version 2.01+ 00443 else if (LinuxSetupSector->Version >= 0x0201) 00444 { 00445 NewStyleLinuxKernel = TRUE; 00446 LinuxSetupSector->HeapEnd = 0x9000; 00447 LinuxSetupSector->LoadFlags |= LINUX_FLAG_CAN_USE_HEAP; 00448 } 00449 00450 if ((NewStyleLinuxKernel == FALSE) && (LinuxHasInitrd == TRUE)) 00451 { 00452 UiMessageBox("Error: Cannot load a ramdisk (initrd) with an old kernel image."); 00453 return FALSE; 00454 } 00455 00456 return TRUE; 00457 } 00458 00459 BOOLEAN LinuxReadInitrd(PFILE LinuxInitrdFile) 00460 { 00461 ULONG BytesLoaded; 00462 CHAR StatusText[260]; 00463 00464 sprintf(StatusText, "Loading %s", LinuxInitrdName); 00465 UiDrawStatusText(StatusText); 00466 00467 // Allocate memory for the ramdisk 00468 //LinuxInitrdLoadAddress = MmAllocateMemory(LinuxInitrdSize); 00469 // Try to align it at the next MB boundary after the kernel 00470 //LinuxInitrdLoadAddress = MmAllocateMemoryAtAddress(LinuxInitrdSize, (PVOID)ROUND_UP((LINUX_KERNEL_LOAD_ADDRESS + LinuxKernelSize), 0x100000)); 00471 if (LinuxSetupSector->Version <= 0x0202) 00472 { 00473 LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LINUX_MAX_INITRD_ADDRESS, LoaderSystemCode); 00474 } 00475 else 00476 { 00477 LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LinuxSetupSector->InitrdAddressMax, LoaderSystemCode); 00478 } 00479 if (LinuxInitrdLoadAddress == NULL) 00480 { 00481 return FALSE; 00482 } 00483 00484 // Set the information in the setup struct 00485 LinuxSetupSector->RamdiskAddress = (ULONG)LinuxInitrdLoadAddress; 00486 LinuxSetupSector->RamdiskSize = LinuxInitrdSize; 00487 00488 TRACE("RamdiskAddress: 0x%x\n", LinuxSetupSector->RamdiskAddress); 00489 TRACE("RamdiskSize: 0x%x\n", LinuxSetupSector->RamdiskSize); 00490 00491 if (LinuxSetupSector->Version >= 0x0203) 00492 { 00493 TRACE("InitrdAddressMax: 0x%x\n", LinuxSetupSector->InitrdAddressMax); 00494 } 00495 00496 // Read in the ramdisk 00497 for (BytesLoaded=0; BytesLoaded<LinuxInitrdSize; ) 00498 { 00499 if (!FsReadFile(LinuxInitrdFile, LINUX_READ_CHUNK_SIZE, NULL, (PVOID)LinuxInitrdLoadAddress)) 00500 { 00501 return FALSE; 00502 } 00503 00504 BytesLoaded += LINUX_READ_CHUNK_SIZE; 00505 LinuxInitrdLoadAddress = (PVOID)((ULONG_PTR)LinuxInitrdLoadAddress + LINUX_READ_CHUNK_SIZE); 00506 00507 UiDrawProgressBarCenter(BytesLoaded + LinuxKernelSize, LinuxInitrdSize + LinuxKernelSize, LinuxBootDescription); 00508 } 00509 00510 return TRUE; 00511 } 00512 #endif /* __i386__ */ 00513 #endif Generated on Fri May 25 2012 04:17:21 for ReactOS by
1.7.6.1
|