reactos操作系统实现(49)

前面已经介绍怎么样从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,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,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,&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文件里执行内核代码了。在内核里,也有一些跟安装有关系的配置,主要就是在内存里创建虚拟磁盘。

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...