前面已经介绍怎么样从ISOBOOT里加载SETUPLDR.SYS,下面来分析一下这个程序与一般硬盘引导程序freeldr.sys有什么区别。
在文件freeldr.c里是这样这样调用安装函数的:
#001 VOID BootMain(LPSTR CmdLine)
#002 {
#003 CmdLineParse(CmdLine);
#004
#005 MachInit(CmdLine);
#006
#007 DebugInit();
#008
#009 DbgPrint((DPRINT_WARNING, "BootMain() called./n"));
#010
#011 if (!UiInitialize(FALSE))
#012 {
#013 UiMessageBoxCritical("Unable to initialize UI./n");
#014 return;
#015 }
#016
#017 if (!MmInitializeMemoryManager())
#018 {
#019 UiMessageBoxCritical("Unable to initialize memory manager");
#020 return;
#021 }
#022
#023 RunLoader();
#024 }
通过上面的函数,然后就调用文件bootmgr.c里的函数RunLoader(),如下:
#001 VOID RunLoader(VOID)
#002 {
......
#098 #ifdef FREELDR_REACTOS_SETUP
#099 else if (_stricmp(SettingValue, "ReactOSSetup") == 0)
#100 {
#101 // In future we could pass the selected OS details through this
#102 // to have different install methods, etc.
#103 LoadReactOSSetup();
#104 }
#105 #endif
......
#143
#144 reboot:
#145 UiUnInitialize("Rebooting...");
#146 return;
#147 }
上面函数调用LoadReactOSSetup函数来加载与一般硬盘引导不一样的代码。而这个函数的代码是在文件setupldr.c里,如下:
#001 VOID LoadReactOSSetup(VOID)
#002 {
#003 ULONG i;
#004 LPCSTR SourcePath;
#005 LPCSTR LoadOptions, DbgLoadOptions = "";
#006 LPCSTR sourcePaths[] = {
#007 "", /* Only for floppy boot */
#008 #if defined(_M_IX86)
#009 "//I386",
#010 #elif defined(_M_MPPC)
#011 "//PPC",
#012 #elif defined(_M_MRX000)
#013 "//MIPS",
#014 #endif
缺省安装的目录。
#015 "//reactos",
#016 NULL };
#017 CHAR FileName[256];
#018
#019 HINF InfHandle;
#020 ULONG ErrorLine;
#021 INFCONTEXT InfContext;
#022 PIMAGE_NT_HEADERS NtHeader;
#023 PVOID LoadBase;
#024
设置多重引导的系统信息。
#025 /* Setup multiboot information structure */
#026 LoaderBlock.CommandLine = reactos_kernel_cmdline;
#027 LoaderBlock.PageDirectoryStart = (ULONG_PTR)&PageDirectoryStart;
#028 LoaderBlock.PageDirectoryEnd = (ULONG_PTR)&PageDirectoryEnd;
#029 LoaderBlock.ModsCount = 0;
#030 LoaderBlock.ModsAddr = reactos_modules;
#031 LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)reactos_memory_map, 32) * sizeof(memory_map_t);
#032 if (LoaderBlock.MmapLength)
#033 {
#034 #if defined (_M_IX86) || defined (_M_AMD64)
#035 ULONG i;
#036 #endif
#037 LoaderBlock.Flags |= MB_FLAGS_MEM_INFO | MB_FLAGS_MMAP_INFO;
#038 LoaderBlock.MmapAddr = (ULONG_PTR)&reactos_memory_map;
#039 reactos_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
#040 #if defined (_M_IX86) || defined (_M_AMD64)
#041 for (i=0; i<(LoaderBlock.MmapLength/sizeof(memory_map_t)); i++)
#042 {
#043 if (BiosMemoryUsable == reactos_memory_map[i].type &&
#044 0 == reactos_memory_map[i].base_addr_low)
#045 {
#046 LoaderBlock.MemLower = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024;
#047 if (640 < LoaderBlock.MemLower)
#048 {
#049 LoaderBlock.MemLower = 640;
#050 }
#051 }
#052 if (BiosMemoryUsable == reactos_memory_map[i].type &&
#053 reactos_memory_map[i].base_addr_low <= 1024 * 1024 &&
#054 1024 * 1024 <= reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low)
#055 {
#056 LoaderBlock.MemHigher = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024 - 1024;
#057 }
#058 }
#059 #endif
#060 }
#061
#062 #ifdef USE_UI
#063 SetupUiInitialize();
#064 #endif
#065 UiDrawStatusText("");
#066
#067 extern BOOLEAN FrLdrBootType;
#068 FrLdrBootType = TRUE;
#069
检测安装电脑的硬件。
#070 /* Detect hardware */
#071 UiDrawStatusText("Detecting hardware...");
#072 LoaderBlock.ArchExtra = (ULONG_PTR)MachHwDetect();
#073 UiDrawStatusText("");
#074
设置引导的设备。
#075 /* set boot device */
#076 MachDiskGetBootDevice(&LoaderBlock.BootDevice);
#077
#078 /* Open boot drive */
#079 if (!FsOpenBootVolume())
#080 {
#081 UiMessageBox("Failed to open boot drive.");
#082 return;
#083 }
#084
加载显示的SIF文件。
#085 UiDrawStatusText("Loading txtsetup.sif...");
#086 /* Open 'txtsetup.sif' */
#087 for (i = MachDiskBootingFromFloppy() ? 0 : 1; ; i++)
#088 {
#089 SourcePath = sourcePaths[i];
#090 if (!SourcePath)
#091 {
#092 printf("Failed to open 'txtsetup.sif'/n");
#093 return;
#094 }
#095 sprintf(FileName,"%s//txtsetup.sif", SourcePath);
#096 if (InfOpenFile (&InfHandle, FileName, &ErrorLine))
#097 break;
#098 }
#099 if (!*SourcePath)
#100 SourcePath = "//";
#101
#102 #ifdef DBG
#103 /* Get load options */
#104 if (InfFindFirstLine (InfHandle,
#105 "SetupData",
#106 "DbgOsLoadOptions",
#107 &InfContext))
#108 {
#109 if (!InfGetDataField (&InfContext, 1, &DbgLoadOptions))
#110 DbgLoadOptions = "";
#111 }
#112 #endif
#113 if (!strlen(DbgLoadOptions) && !InfFindFirstLine (InfHandle,
#114 "SetupData",
#115 "OsLoadOptions",
#116 &InfContext))
#117 {
#118 printf("Failed to find 'SetupData/OsLoadOptions'/n");
#119 return;
#120 }
#121
#122 if (!InfGetDataField (&InfContext,
#123 1,
#124 &LoadOptions))
#125 {
#126 printf("Failed to get load options/n");
#127 return;
#128 }
#129
设置内核的命令行参数。
#130 /* Set kernel command line */
#131 MachDiskGetBootPath(reactos_kernel_cmdline, sizeof(reactos_kernel_cmdline));
#132 strcat(strcat(strcat(strcat(reactos_kernel_cmdline, SourcePath), " "),
#133 LoadOptions), DbgLoadOptions);
#134
设置引导的路径和内核。
#135 /* Setup the boot path and kernel path */
#136 strcpy(szBootPath, SourcePath);
#137
#138 sprintf(SystemRoot,"%s//", SourcePath);
#139 sprintf(FileName,"%s//ntoskrnl.exe", SourcePath);
#140 sprintf(szHalName,"%s//hal.dll", SourcePath);
#141
加载内核和硬件抽象层。
#142 /* Load the kernel */
#143 LoadBase = FrLdrLoadImage(FileName, 5, 1);
#144 if (!LoadBase) return;
#145
#146 /* Get the NT header, kernel base and kernel entry */
#147 NtHeader = RtlImageNtHeader(LoadBase);
#148 KernelBase = SWAPD(NtHeader->OptionalHeader.ImageBase);
#149 KernelEntryPoint = (ROS_KERNEL_ENTRY_POINT)(KernelBase + SWAPD(NtHeader->OptionalHeader.AddressOfEntryPoint));
#150 LoaderBlock.KernelBase = KernelBase;
#151
#152 /* Insert boot disk 2 */
#153 if (MachDiskBootingFromFloppy())
#154 {
#155 UiMessageBox("Please insert /"ReactOS Boot Disk 2/" and press ENTER");
#156
#157 /* Open boot drive */
#158 if (!FsOpenBootVolume())
#159 {
#160 UiMessageBox("Failed to open boot drive.");
#161 return;
#162 }
#163
#164 /* FIXME: check volume label or disk marker file */
#165 }
#166
#167
获取ANSI的代码表文件。
#168 /* Get ANSI codepage file */
#169 if (!InfFindFirstLine (InfHandle,
#170 "NLS",
#171 "AnsiCodepage",
#172 &InfContext))
#173 {
#174 printf("Failed to find 'NLS/AnsiCodepage'/n");
#175 return;
#176 }
#177
#178 if (!InfGetDataField (&InfContext,
#179 1,
#180 &LoadOptions))
#181 {
#182 printf("Failed to get load options/n");
#183 return;
#184 }
#185
#186 sprintf(FileName,"%s//%s", SourcePath,LoadOptions);
#187 /* Load ANSI codepage file */
#188 if (!FrLdrLoadNlsFile(FileName, "ansi.nls"))
#189 {
#190 UiMessageBox("Failed to load the ANSI codepage file.");
#191 return;
#192 }
#193
#194 /* Get OEM codepage file */
#195 if (!InfFindFirstLine (InfHandle,
#196 "NLS",
#197 "OemCodepage",
#198 &InfContext))
#199 {
#200 printf("Failed to find 'NLS/AnsiCodepage'/n");
#201 return;
#202 }
#203
#204 if (!InfGetDataField (&InfContext,
#205 1,
#206 &LoadOptions))
#207 {
#208 printf("Failed to get load options/n");
#209 return;
#210 }
#211
#212 sprintf(FileName,"%s//%s", SourcePath,LoadOptions);
#213 /* Load OEM codepage file */
#214 if (!FrLdrLoadNlsFile(FileName, "oem.nls"))
#215 {
#216 UiMessageBox("Failed to load the OEM codepage file.");
#217 return;
#218 }
#219
#220 /* Get Unicode Casemap file */
#221 if (!InfFindFirstLine (InfHandle,
#222 "NLS",
#223 "UnicodeCasetable",
#224 &InfContext))
#225 {
#226 printf("Failed to find 'NLS/AnsiCodepage'/n");
#227 return;
#228 }
#229
#230 if (!InfGetDataField (&InfContext,
#231 1,
#232 &LoadOptions))
#233 {
#234 printf("Failed to get load options/n");
#235 return;
#236 }
#237
#238 sprintf(FileName,"%s//%s", SourcePath,LoadOptions);
#239 /* Load Unicode casemap file */
#240 if (!FrLdrLoadNlsFile(FileName, "casemap.nls"))
#241 {
#242 UiMessageBox("Failed to load the Unicode casemap file.");
#243 return;
#244 }
#245
#246 /* Load additional files specified in txtsetup.inf */
#247 if (InfFindFirstLine(InfHandle,
#248 "SourceDisksFiles",
#249 NULL,
#250 &InfContext))
#251 {
#252 do
#253 {
#254 LPCSTR Media, DriverName;
#255 if (InfGetDataField(&InfContext, 7, &Media) &&
#256 InfGetDataField(&InfContext, 0, &DriverName))
#257 {
#258 if (strcmp(Media, "x") == 0)
#259 {
#260 if (!FrLdrLoadDriver((PCHAR)DriverName,0))
#261 return;
#262 }
#263 }
#264 } while (InfFindNextLine(&InfContext, &InfContext));
#265 }
#266
显示开始引导ReactOS。
#267 UiUnInitialize("Booting ReactOS...");
#268
#269
#270 //
#271 // Perform architecture-specific pre-boot configuration
#272 //
#273 MachPrepareForReactOS(TRUE);
#274
这里跳到内核代码执行。
#275 //
#276 // Setup paging and jump to kernel
#277 //
#278 FrLdrStartup(0x2badb002);
#279 }
后面加载函数FrLdrStartup,与最前面讨论的引导是一样功能了,最后就跳到ntoskrnl.exe文件里执行内核代码了。在内核里,也有一些跟安装有关系的配置,主要就是在内存里创建虚拟磁盘。