ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

linuxboot.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.