Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

561 lines
14 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. main.c
  5. Abstract:
  6. Main for the SU (startup) module for the OS loader. The SU module
  7. must take the x86 from a real-mode 16bit state to a FLAT model,
  8. 32bit protect/paging enabled state.
  9. Author:
  10. Thomas Parslow (tomp) Created 20-Dec-90
  11. Revision History:
  12. --*/
  13. #define NTAPI
  14. #include "su.h"
  15. #include "eisa.h"
  16. #define _SYS_GUID_OPERATORS_
  17. #include <guiddef.h>
  18. #include "ntimage.h"
  19. #include "strings.h"
  20. extern VOID RealMode(VOID);
  21. extern USHORT IDTregisterZero;
  22. extern IMAGE_DOS_HEADER edata;
  23. extern USHORT end;
  24. extern VOID MoveMemory(ULONG,ULONG,ULONG);
  25. extern USHORT SuStackBegin;
  26. extern UCHAR Beginx86Relocation;
  27. extern UCHAR Endx86Relocation;
  28. extern USHORT BackEnd;
  29. extern ULONG FileStart;
  30. extern BOOLEAN IsNpxPresent(VOID);
  31. extern USHORT HwGetProcessorType(VOID);
  32. extern USHORT HwGetCpuStepping(USHORT);
  33. extern ULONG MachineType;
  34. extern ULONG OsLoaderStart;
  35. extern ULONG OsLoaderEnd;
  36. extern ULONG ResourceDirectory;
  37. extern ULONG ResourceOffset;
  38. extern ULONG OsLoaderBase;
  39. extern ULONG OsLoaderExports;
  40. extern
  41. TurnMotorOff(
  42. VOID
  43. );
  44. extern
  45. EnableA20(
  46. VOID
  47. );
  48. extern
  49. BOOLEAN
  50. ConstructMemoryDescriptors(
  51. VOID
  52. );
  53. extern
  54. USHORT
  55. IsaConstructMemoryDescriptors(
  56. VOID
  57. );
  58. VOID
  59. Relocatex86Structures(
  60. VOID
  61. );
  62. ULONG
  63. RelocateLoaderSections(
  64. OUT PULONG Start,
  65. OUT PULONG End
  66. );
  67. extern
  68. FSCONTEXT_RECORD
  69. FsContext;
  70. #define DISK_TABLE_VECTOR (0x1e*4)
  71. FPULONG DiskTableVector = (FPULONG)(DISK_TABLE_VECTOR);
  72. VOID
  73. SuMain(
  74. IN UCHAR BtBootDrive
  75. )
  76. /*++
  77. Routine Description:
  78. Main entrypoint of the SU module. Control is passed from the boot
  79. sector to startup.asm which does some run-time fixups on the stack
  80. and data segments and then passes control here.
  81. Arguments:
  82. BtBootDrive - Drive that we booted from (int13 unit number)
  83. Returns:
  84. Does not return. Passes control to the OS loader
  85. --*/
  86. {
  87. ULONG LoaderEntryPoint;
  88. ULONG EisaNumPages;
  89. USHORT IsaNumPages;
  90. MEMORY_LIST_ENTRY _far *CurrentEntry;
  91. PIMAGE_OPTIONAL_HEADER OptionalHeader;
  92. ULONG BlockEnd;
  93. ULONG ImageSize;
  94. ULONG ImageBase;
  95. //
  96. // Save fs context info
  97. //
  98. FsContext.BootDrive = BtBootDrive;
  99. //
  100. // Initialize the video subsystem first so that
  101. // errors end exceptions can be displayed.
  102. //
  103. InitializeVideoSubSystem();
  104. //
  105. // In case we booted from a floppy, turn the drive motor off.
  106. //
  107. TurnMotorOff();
  108. //
  109. // Set up machine type based on its Bus type.
  110. //
  111. if (BtIsEisaSystem()) {
  112. MachineType = MACHINE_TYPE_EISA;
  113. } else {
  114. MachineType = MACHINE_TYPE_ISA;
  115. }
  116. if (!ConstructMemoryDescriptors()) {
  117. //
  118. // If INT 15 E802h fails...
  119. //
  120. if (MachineType == MACHINE_TYPE_EISA) {
  121. //
  122. // HACKHACK John Vert (jvert)
  123. // This is completely bogus. Since there are a number of EISA
  124. // machines which do not let you correctly configure the EISA
  125. // NVRAM, and even MORE machines which are improperly configured,
  126. // we first check to see how much memory the ISA routines say
  127. // exists. Then we check what the EISA routines tell us, and
  128. // compare the two. If the EISA number is much lower (where "much"
  129. // is a completely random fudge factor) than the ISA number, we
  130. // assume the machine is improperly configured and we throw away
  131. // the EISA numbers and use the ISA ones. If not, we assume that
  132. // the machine is actually configured properly and we trust the
  133. // EISA numbers..
  134. //
  135. IsaNumPages = IsaConstructMemoryDescriptors();
  136. EisaNumPages = EisaConstructMemoryDescriptors();
  137. if (EisaNumPages + 0x80 < IsaNumPages) {
  138. IsaConstructMemoryDescriptors();
  139. }
  140. } else {
  141. IsaConstructMemoryDescriptors();
  142. }
  143. }
  144. //
  145. // Search for memory descriptor describing low memory
  146. //
  147. CurrentEntry = MemoryDescriptorList;
  148. while ((CurrentEntry->BlockBase != 0) &&
  149. (CurrentEntry->BlockSize != 0)) {
  150. CurrentEntry++;
  151. }
  152. if ((CurrentEntry->BlockBase == 0) &&
  153. (CurrentEntry->BlockSize < (ULONG)512 * (ULONG)1024)) {
  154. BlPrint(SU_NO_LOW_MEMORY,CurrentEntry->BlockSize/1024);
  155. while (1) {
  156. }
  157. }
  158. //
  159. // Ensure there is a memory descriptor to contain osloader image
  160. //
  161. OptionalHeader = &((PIMAGE_NT_HEADERS) ((PUCHAR) &edata + edata.e_lfanew))->OptionalHeader;
  162. ImageBase = OptionalHeader->ImageBase;
  163. ImageSize = OptionalHeader->SizeOfImage;
  164. OsLoaderBase = ImageBase;
  165. OsLoaderExports = ImageBase + OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  166. CurrentEntry = MemoryDescriptorList;
  167. while (ImageSize > 0) {
  168. while (CurrentEntry->BlockSize != 0) {
  169. BlockEnd = CurrentEntry->BlockBase + CurrentEntry->BlockSize;
  170. if ((CurrentEntry->BlockBase <= ImageBase) &&
  171. (BlockEnd > ImageBase)) {
  172. //
  173. // this descriptor at least partially contains a chunk
  174. // of the osloader.
  175. //
  176. if (BlockEnd-ImageBase > ImageSize) {
  177. ImageSize = 0;
  178. } else {
  179. ImageSize -= (BlockEnd-ImageBase);
  180. ImageBase = BlockEnd;
  181. }
  182. //
  183. // look for remaining part (if any) of osloader
  184. //
  185. CurrentEntry = MemoryDescriptorList;
  186. break;
  187. }
  188. CurrentEntry++;
  189. }
  190. if (CurrentEntry->BlockSize == 0) {
  191. break;
  192. }
  193. }
  194. if (ImageSize > 0) {
  195. //
  196. // We could not relocate the osloader to high memory. Error out
  197. // and display the memory map.
  198. //
  199. BlPrint(SU_NO_EXTENDED_MEMORY);
  200. CurrentEntry = MemoryDescriptorList;
  201. while (CurrentEntry->BlockSize != 0) {
  202. BlPrint(" %lx - %lx\n",
  203. CurrentEntry->BlockBase,
  204. CurrentEntry->BlockBase + CurrentEntry->BlockSize);
  205. CurrentEntry++;
  206. }
  207. while (1) {
  208. }
  209. }
  210. //
  211. // Enable the A20 line for protect mode
  212. //
  213. EnableA20();
  214. //
  215. // Relocate x86 structures. This includes the GDT, IDT,
  216. // page directory, and first level page table.
  217. //
  218. Relocatex86Structures();
  219. //
  220. // Enable protect and paging modes for the first time
  221. //
  222. EnableProtectPaging(ENABLING);
  223. //
  224. // Go relocate loader sections and build page table entries
  225. //
  226. LoaderEntryPoint = RelocateLoaderSections(&OsLoaderStart, &OsLoaderEnd);
  227. //
  228. // Search for memory descriptor containing the osloader and
  229. // change it.
  230. //
  231. //
  232. // Transfer control to the OS loader
  233. //
  234. TransferToLoader(LoaderEntryPoint);
  235. }
  236. ULONG
  237. RelocateLoaderSections(
  238. OUT PULONG Start,
  239. OUT PULONG End
  240. )
  241. /*++
  242. Routine Description:
  243. The SU module is prepended to the OS loader file. The OS loader file
  244. is a coff++ file. This routine computes the beginning of the OS loader
  245. file, then relocates the OS loader's sections as if it were just
  246. loading the file from disk file.
  247. Arguments:
  248. Start - Returns the address of the start of the image
  249. End - Returns the address of the end of the image
  250. Returns:
  251. Entry point of loader
  252. --*/
  253. {
  254. USHORT Section;
  255. ULONG Source,Destination;
  256. ULONG VirtualSize;
  257. ULONG SizeOfRawData;
  258. PIMAGE_FILE_HEADER FileHeader;
  259. PIMAGE_OPTIONAL_HEADER OptionalHeader;
  260. PIMAGE_SECTION_HEADER SectionHeader;
  261. //
  262. // Make a pointer to the beginning of the loader's coff header
  263. //
  264. FileHeader = &((PIMAGE_NT_HEADERS) ((PUCHAR) &edata + edata.e_lfanew))->FileHeader;
  265. //
  266. // Validate the appended loader image by checking signatures.
  267. // 1st - is it an executable image?
  268. // 2nd - is the target environment the 386?
  269. //
  270. if ((FileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0) {
  271. puts(SU_NTLDR_CORRUPT);
  272. WAITFOREVER;
  273. }
  274. if (FileHeader->Machine != IMAGE_FILE_MACHINE_I386) {
  275. puts(SU_NTLDR_CORRUPT);
  276. WAITFOREVER;
  277. }
  278. //
  279. // Make a pointer to the optional header in the header-buffer
  280. //
  281. OptionalHeader = (PIMAGE_OPTIONAL_HEADER)((PUCHAR)FileHeader +
  282. sizeof(IMAGE_FILE_HEADER));
  283. //
  284. // Make a pointer to the first section in the header buffer
  285. //
  286. SectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)OptionalHeader +
  287. FileHeader->SizeOfOptionalHeader);
  288. *Start = OptionalHeader->ImageBase+SectionHeader->VirtualAddress;
  289. *End = *Start + SectionHeader->SizeOfRawData;
  290. //
  291. // Display some debug stuff for now
  292. //
  293. DBG1(
  294. BlPrint("Machine = %x\n",FileHeader->Machine);
  295. BlPrint("NumberOfSections = %x\n",FileHeader->NumberOfSections);
  296. BlPrint("TimeDateStamp %lx\n",FileHeader->TimeDateStamp);
  297. BlPrint("PointerToSymbolTable = %lx\n",FileHeader->PointerToSymbolTable);
  298. BlPrint("NumberOfSymbols %lx\n",FileHeader->NumberOfSymbols);
  299. BlPrint("SizeOfOptionalHeader = %x\n",FileHeader->SizeOfOptionalHeader);
  300. BlPrint("Characteristics = %x\n",FileHeader->Characteristics);
  301. )
  302. //
  303. // Loop and relocate each section with a non-zero RawData size
  304. //
  305. for (Section=FileHeader->NumberOfSections ; Section-- ; SectionHeader++) {
  306. //
  307. // Compute source, destination, and count arguments
  308. //
  309. Source = FileStart + SectionHeader->PointerToRawData;
  310. Destination = OptionalHeader->ImageBase + SectionHeader->VirtualAddress;
  311. VirtualSize = SectionHeader->Misc.VirtualSize;
  312. SizeOfRawData = SectionHeader->SizeOfRawData;
  313. if (VirtualSize == 0) {
  314. VirtualSize = SizeOfRawData;
  315. }
  316. if (SectionHeader->PointerToRawData == 0) {
  317. //
  318. // SizeOfRawData can be non-zero even if PointerToRawData is zero
  319. //
  320. SizeOfRawData = 0;
  321. } else if (SizeOfRawData > VirtualSize) {
  322. //
  323. // Don't load more from image than is expected in memory
  324. //
  325. SizeOfRawData = VirtualSize;
  326. }
  327. if (Destination < *Start) {
  328. *Start = Destination;
  329. }
  330. if (Destination+VirtualSize > *End) {
  331. *End = Destination+VirtualSize;
  332. }
  333. DBG1(BlPrint("src=%lx dest=%lx raw=%lx\n",Source,Destination,SizeOfRawData);)
  334. if (SizeOfRawData != 0) {
  335. //
  336. // This section is either a code (.TEXT) section or an
  337. // initialized data (.DATA) section.
  338. // Relocate the section to memory at the virtual/physical
  339. // addresses specified in the section header.
  340. //
  341. MoveMemory(Source,Destination,SizeOfRawData);
  342. }
  343. if (SizeOfRawData < VirtualSize) {
  344. //
  345. // Zero the portion not loaded from the image
  346. //
  347. DBG1( BlPrint("Zeroing destination %lx\n",Destination+SizeOfRawData); )
  348. ZeroMemory(Destination+SizeOfRawData,VirtualSize - SizeOfRawData);
  349. }
  350. //
  351. // Check if this is the resource section. If so, we need
  352. // to pass its location to the osloader.
  353. //
  354. if ((SectionHeader->Name[0] == '.') &&
  355. (SectionHeader->Name[1] == 'r') &&
  356. (SectionHeader->Name[2] == 's') &&
  357. (SectionHeader->Name[3] == 'r') &&
  358. (SectionHeader->Name[4] == 'c')) {
  359. ResourceDirectory = Destination;
  360. ResourceOffset = SectionHeader->VirtualAddress;
  361. }
  362. }
  363. DBG1( BlPrint("RelocateLoaderSections done - EntryPoint == %lx\n",
  364. OptionalHeader->AddressOfEntryPoint + OptionalHeader->ImageBase);)
  365. return(OptionalHeader->AddressOfEntryPoint + OptionalHeader->ImageBase);
  366. }
  367. VOID
  368. Relocatex86Structures(
  369. VOID
  370. )
  371. /*++
  372. Routine Description:
  373. The gdt and idt are statically defined and imbedded in the SU modules
  374. data segment. This routine moves then out of the data segment and into
  375. a page mapped at a defined location.
  376. Arguments:
  377. None
  378. Returns:
  379. Nothing
  380. --*/
  381. {
  382. FPUCHAR Fpsrc, Fpdst;
  383. USHORT Count;
  384. //
  385. // Make pointers to the data and compute the size
  386. // of the block to use.
  387. //
  388. Fpsrc = (FPUCHAR)&Beginx86Relocation;
  389. MAKE_FP(Fpdst,SYSTEM_STRUCTS_BASE_PA);
  390. Count = (&Endx86Relocation - &Beginx86Relocation);
  391. //
  392. // Move the data to its new location
  393. //
  394. while (Count--) {
  395. *Fpdst++ = *Fpsrc++;
  396. }
  397. }
  398. VOID
  399. DisplayArgs(
  400. USHORT es,
  401. USHORT bx,
  402. USHORT cx,
  403. USHORT dx,
  404. USHORT ax
  405. )
  406. /*++
  407. Routine Description:
  408. Just a debugging routine to dump some registers.
  409. Arguments:
  410. The x86 registers es, bx, cx, dx, and ax are pushed on the stack
  411. before this routine is called.
  412. Returns:
  413. Nothing
  414. Environment:
  415. Real Mode ONLY
  416. --*/
  417. {
  418. BlPrint("ax:%x dx:%x cx:%x bx:%x es:%x\n",
  419. (USHORT) ax,
  420. (USHORT) dx,
  421. (USHORT) cx,
  422. (USHORT) bx,
  423. (USHORT) es);
  424. return;
  425. }
  426. // END OF FILE //