[NTOS]: Add a branch-to-self to start testing kernel code.
[reactos.git] / reactos / boot / freeldr / freeldr / arch / arm / loader.c
1 /*
2 * PROJECT: ReactOS Boot Loader
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/freeldr/arch/arm/loader.c
5 * PURPOSE: ARM Kernel Loader
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <freeldr.h>
12 #include <internal/arm/ke.h>
13 #include <internal/arm/mm.h>
14 #include <internal/arm/intrin_i.h>
15
16 #define KERNEL_DESCRIPTOR_PAGE(x) (((ULONG_PTR)x &~ KSEG0_BASE) >> PAGE_SHIFT)
17
18 /* GLOBALS ********************************************************************/
19
20 typedef struct _BIOS_MEMORY_DESCRIPTOR
21 {
22 ULONG BlockBase;
23 ULONG BlockSize;
24 } BIOS_MEMORY_DESCRIPTOR, *PBIOS_MEMORY_DESCRIPTOR;
25
26 ULONG PageDirectoryStart, PageDirectoryEnd;
27 PLOADER_PARAMETER_BLOCK ArmLoaderBlock;
28 CHAR ArmCommandLine[256];
29 CHAR ArmArcBootPath[64];
30 CHAR ArmArcHalPath[64];
31 CHAR ArmNtHalPath[64];
32 CHAR ArmNtBootPath[64];
33 PNLS_DATA_BLOCK ArmNlsDataBlock;
34 PLOADER_PARAMETER_EXTENSION ArmExtension;
35 BIOS_MEMORY_DESCRIPTOR ArmBoardMemoryDescriptors[16] = {{0}};
36 PBIOS_MEMORY_DESCRIPTOR ArmBoardMemoryList = ArmBoardMemoryDescriptors;
37 ULONG NumberDescriptors = 0;
38 MEMORY_DESCRIPTOR MDArray[16] = {{0}};
39 ULONG ArmSharedHeapSize;
40 PCHAR ArmSharedHeap;
41
42 extern PAGE_DIRECTORY_ARM startup_pagedirectory;
43 extern PAGE_TABLE_ARM kernel_pagetable;
44 extern ROS_KERNEL_ENTRY_POINT KernelEntryPoint;
45 extern ULONG_PTR KernelBase;
46
47 extern ADDRESS_RANGE ArmBoardMemoryMap[16];
48 extern ULONG ArmBoardMemoryMapRangeCount;
49 extern ULONG_PTR AnsiData, OemData, UnicodeData, RegistryData, KernelData, HalData, DriverData[16];
50 extern ULONG RegistrySize, AnsiSize, OemSize, UnicodeSize, KernelSize, HalSize, DriverSize[16];
51 extern PCHAR DriverName[16];
52 extern ULONG Drivers;
53 extern ULONG BootStack;
54
55 ULONG SizeBits[] =
56 {
57 -1, // INVALID
58 -1, // INVALID
59 1 << 12, // 4KB
60 1 << 13, // 8KB
61 1 << 14, // 16KB
62 1 << 15, // 32KB
63 1 << 16, // 64KB
64 1 << 17 // 128KB
65 };
66
67 ULONG AssocBits[] =
68 {
69 -1, // INVALID
70 -1, // INVALID
71 4 // 4-way associative
72 };
73
74 ULONG LenBits[] =
75 {
76 -1, // INVALID
77 -1, // INVALID
78 8 // 8 words per line (32 bytes)
79 };
80
81 //
82 // Where to map the serial port
83 //
84 #define UART_VIRTUAL 0xE0000000
85
86 /* FUNCTIONS ******************************************************************/
87
88 PVOID
89 ArmAllocateFromSharedHeap(IN ULONG Size)
90 {
91 PVOID Buffer;
92
93 //
94 // Allocate from the shared heap
95 //
96 Buffer = &ArmSharedHeap[ArmSharedHeapSize];
97 ArmSharedHeapSize += Size;
98 return Buffer;
99 }
100
101 PMEMORY_ALLOCATION_DESCRIPTOR
102 NTAPI
103 ArmAllocateMemoryDescriptor(VOID)
104 {
105 //
106 // Allocate a descriptor from the heap
107 //
108 return ArmAllocateFromSharedHeap(sizeof(MEMORY_ALLOCATION_DESCRIPTOR));
109 }
110
111 VOID
112 NTAPI
113 ArmAddBoardMemoryDescriptor(IN ULONG Address,
114 IN ULONG Size)
115 {
116 PBIOS_MEMORY_DESCRIPTOR BiosBlock = ArmBoardMemoryList;
117
118 //
119 // Loop board DRAM configuration
120 //
121 while (BiosBlock->BlockSize > 0)
122 {
123 /* Check if we've found a matching head block */
124 if (Address + Size == BiosBlock->BlockBase)
125 {
126 /* Simply enlarge and rebase it */
127 BiosBlock->BlockBase = Address;
128 BiosBlock->BlockSize += Size;
129 break;
130 }
131
132 /* Check if we've found a matching tail block */
133 if (Address == (BiosBlock->BlockBase + BiosBlock->BlockSize))
134 {
135 /* Simply enlarge it */
136 BiosBlock->BlockSize += Size;
137 break;
138 }
139
140 /* Nothing suitable found, try the next block */
141 BiosBlock++;
142 }
143
144 /* No usable blocks found, found a free block instead */
145 if (!BiosBlock->BlockSize)
146 {
147 /* Write our data */
148 BiosBlock->BlockBase = Address;
149 BiosBlock->BlockSize = Size;
150
151 /* Create a new block and mark it as the end of the array */
152 BiosBlock++;
153 BiosBlock->BlockBase = BiosBlock->BlockSize = 0L;
154 }
155 }
156
157 VOID
158 NTAPI
159 ArmBuildBoardMemoryMap(VOID)
160 {
161 ULONG BlockBegin, BlockEnd;
162 ULONG j;
163
164 /* Loop the BIOS Memory Map */
165 for (j = 0; j < ArmBoardMemoryMapRangeCount; j++)
166 {
167 /* Get the start and end addresses */
168 BlockBegin = ArmBoardMemoryMap[j].BaseAddrLow;
169 BlockEnd = ArmBoardMemoryMap[j].BaseAddrLow + ArmBoardMemoryMap[j].LengthLow - 1;
170
171 /* Make sure this isn't a > 4GB descriptor */
172 if (!ArmBoardMemoryMap[j].BaseAddrHigh)
173 {
174 /* Make sure we don't overflow */
175 if (BlockEnd < BlockBegin) BlockEnd = 0xFFFFFFFF;
176
177 /* Check if this is free memory */
178 if (ArmBoardMemoryMap[j].Type == 1)
179 {
180 /* Add it to our BIOS descriptors */
181 ArmAddBoardMemoryDescriptor(BlockBegin, BlockEnd - BlockBegin + 1);
182 }
183 }
184 }
185 }
186
187 NTSTATUS
188 NTAPI
189 ArmConfigureArcDescriptor(IN ULONG PageBegin,
190 IN ULONG PageEnd,
191 IN TYPE_OF_MEMORY MemoryType)
192 {
193 ULONG i;
194 ULONG BlockBegin, BlockEnd;
195 MEMORY_TYPE BlockType;
196 BOOLEAN Combined = FALSE;
197
198 /* If this descriptor seems bogus, just return */
199 if (PageEnd <= PageBegin) return STATUS_SUCCESS;
200
201 /* Loop every ARC descriptor, trying to find one we can modify */
202 for (i = 0; i < NumberDescriptors; i++)
203 {
204 /* Get its settings */
205 BlockBegin = MDArray[i].BasePage;
206 BlockEnd = MDArray[i].BasePage + MDArray[i].PageCount;
207 BlockType = MDArray[i].MemoryType;
208
209 /* Check if we can fit inside this block */
210 if (BlockBegin < PageBegin)
211 {
212 /* Check if we are larger then it */
213 if ((BlockEnd > PageBegin) && (BlockEnd <= PageEnd))
214 {
215 /* Make it end where we start */
216 BlockEnd = PageBegin;
217 }
218
219 /* Check if it ends after we do */
220 if (BlockEnd > PageEnd)
221 {
222 /* Make sure we can allocate a descriptor */
223 if (NumberDescriptors == 60) return ENOMEM;
224
225 /* Create a descriptor for whatever memory we're not part of */
226 MDArray[NumberDescriptors].MemoryType = BlockType;
227 MDArray[NumberDescriptors].BasePage = PageEnd;
228 MDArray[NumberDescriptors].PageCount = BlockEnd - PageEnd;
229 NumberDescriptors++;
230
231 /* The next block ending is now where we begin */
232 BlockEnd = PageBegin;
233 }
234 }
235 else
236 {
237 /* Check if the blog begins inside our range */
238 if (BlockBegin < PageEnd)
239 {
240 /* Check if it ends before we do */
241 if (BlockEnd < PageEnd)
242 {
243 /* Then make it disappear */
244 BlockEnd = BlockBegin;
245 }
246 else
247 {
248 /* Otherwise make it start where we end */
249 BlockBegin = PageEnd;
250 }
251 }
252 }
253
254 /* Check if the block matches us, and we haven't tried combining yet */
255 if ((BlockType == MemoryType) && !(Combined))
256 {
257 /* Check if it starts where we end */
258 if (BlockBegin == PageEnd)
259 {
260 /* Make it start with us, and combine us */
261 BlockBegin = PageBegin;
262 Combined = TRUE;
263 }
264 else if (BlockEnd == PageBegin)
265 {
266 /* Otherwise, it ends where we begin, combine its ending */
267 BlockEnd = PageEnd;
268 Combined = TRUE;
269 }
270 }
271
272 /* Check the original block data matches with what we came up with */
273 if ((MDArray[i].BasePage == BlockBegin) &&
274 (MDArray[i].PageCount == BlockEnd - BlockBegin))
275 {
276 /* Then skip it */
277 continue;
278 }
279
280 /* Otherwise, set our new settings for this block */
281 MDArray[i].BasePage = BlockBegin;
282 MDArray[i].PageCount = BlockEnd - BlockBegin;
283
284 /* Check if we are killing the block */
285 if (BlockBegin == BlockEnd)
286 {
287 /* Delete this block and restart the loop properly */
288 NumberDescriptors--;
289 if (i < NumberDescriptors) MDArray[i] = MDArray[NumberDescriptors];
290 i--;
291 }
292 }
293
294 /* If we got here without combining, we need to allocate a new block */
295 if (!(Combined) && (MemoryType < LoaderMaximum))
296 {
297 /* Make sure there's enough descriptors */
298 if (NumberDescriptors == 60) return ENOMEM;
299
300 /* Allocate a new block with our data */
301 MDArray[NumberDescriptors].MemoryType = MemoryType;
302 MDArray[NumberDescriptors].BasePage = PageBegin;
303 MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
304 NumberDescriptors++;
305 }
306
307 /* Changes complete, return success */
308 return STATUS_SUCCESS;
309 }
310
311 NTSTATUS
312 NTAPI
313 ArmBuildOsMemoryMap(VOID)
314 {
315 PBIOS_MEMORY_DESCRIPTOR MdBlock;
316 ULONG BlockStart, BlockEnd, BiasedStart, BiasedEnd, PageStart, PageEnd;
317 NTSTATUS Status = STATUS_SUCCESS;
318
319 /* Loop the BIOS Memory Descriptor List */
320 MdBlock = ArmBoardMemoryList;
321 while (MdBlock->BlockSize)
322 {
323 /* Get the statrt and end addresses */
324 BlockStart = MdBlock->BlockBase;
325 BlockEnd = BlockStart + MdBlock->BlockSize - 1;
326
327 /* Align them to page boundaries */
328 BiasedStart = BlockStart & (PAGE_SIZE - 1);
329 if (BiasedStart) BlockStart = BlockStart + PAGE_SIZE - BiasedStart;
330 BiasedEnd = (BlockEnd + 1) & (ULONG)(PAGE_SIZE - 1);
331 if (BiasedEnd) BlockEnd -= BiasedEnd;
332
333 /* Get the actual page numbers */
334 PageStart = BlockStart >> PAGE_SHIFT;
335 PageEnd = (BlockEnd + 1) >> PAGE_SHIFT;
336
337 /* Check if we did any alignment */
338 if (BiasedStart)
339 {
340 /* Mark that region as reserved */
341 Status = ArmConfigureArcDescriptor(PageStart - 1,
342 PageStart,
343 MemorySpecialMemory);
344 if (Status != STATUS_SUCCESS) break;
345 }
346
347 /* Check if we did any alignment */
348 if (BiasedEnd)
349 {
350 /* Mark that region as reserved */
351 Status = ArmConfigureArcDescriptor(PageEnd - 1,
352 PageEnd,
353 MemorySpecialMemory);
354 if (Status != STATUS_SUCCESS) break;
355 }
356
357 /* It is, mark the memory a free */
358 Status = ArmConfigureArcDescriptor(PageStart,
359 PageEnd,
360 LoaderFree);
361
362 /* If we failed, break out, otherwise, go to the next BIOS block */
363 if (Status != STATUS_SUCCESS) break;
364 MdBlock++;
365 }
366
367 /* Return error code */
368 return Status;
369 }
370
371 VOID
372 NTAPI
373 ArmInsertMemoryDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
374 {
375 PLIST_ENTRY ListHead, PreviousEntry, NextEntry;
376 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor = NULL, NextDescriptor = NULL;
377
378 /* Loop the memory descriptor list */
379 ListHead = &ArmLoaderBlock->MemoryDescriptorListHead;
380 PreviousEntry = ListHead;
381 NextEntry = ListHead->Flink;
382 while (NextEntry != ListHead)
383 {
384 /* Get the current descriptor and check if it's below ours */
385 NextDescriptor = CONTAINING_RECORD(NextEntry,
386 MEMORY_ALLOCATION_DESCRIPTOR,
387 ListEntry);
388 if (NewDescriptor->BasePage < NextDescriptor->BasePage) break;
389
390 /* It isn't, save the previous entry and descriptor, and try again */
391 PreviousEntry = NextEntry;
392 Descriptor = NextDescriptor;
393 NextEntry = NextEntry->Flink;
394 }
395
396 /* So we found the right spot to insert. Is this free memory? */
397 if (NewDescriptor->MemoryType != LoaderFree)
398 {
399 /* It isn't, so insert us before the last descriptor */
400 InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
401 }
402 else
403 {
404 /* We're free memory. Check if the entry we found is also free memory */
405 if ((PreviousEntry != ListHead) &&
406 ((Descriptor->MemoryType == LoaderFree) ||
407 (Descriptor->MemoryType == LoaderReserve)) &&
408 ((Descriptor->BasePage + Descriptor->PageCount) ==
409 NewDescriptor->BasePage))
410 {
411 /* It's free memory, and we're right after it. Enlarge that block */
412 Descriptor->PageCount += NewDescriptor->PageCount;
413 NewDescriptor = Descriptor;
414 }
415 else
416 {
417 /* Our range scan't be combined, so just insert us separately */
418 InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
419 }
420
421 /* Check if we merged with an existing free memory block */
422 if ((NextEntry != ListHead) &&
423 ((NextDescriptor->MemoryType == LoaderFree) ||
424 (NextDescriptor->MemoryType == LoaderReserve)) &&
425 ((NewDescriptor->BasePage + NewDescriptor->PageCount) ==
426 NextDescriptor->BasePage))
427 {
428 /* Update our own block */
429 NewDescriptor->PageCount += NextDescriptor->PageCount;
430
431 /* Remove the next block */
432 RemoveEntryList(&NextDescriptor->ListEntry);
433 }
434 }
435 }
436
437 NTSTATUS
438 NTAPI
439 ArmBuildMemoryDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor,
440 IN MEMORY_TYPE MemoryType,
441 IN ULONG BasePage,
442 IN ULONG PageCount)
443 {
444 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor, NextDescriptor = NULL;
445 LONG Delta;
446 TYPE_OF_MEMORY CurrentType;
447 BOOLEAN UseNext;
448
449 /* Check how many pages we'll be consuming */
450 Delta = BasePage - MemoryDescriptor->BasePage;
451 if (!(Delta) && (PageCount == MemoryDescriptor->PageCount))
452 {
453 /* We can simply convert the current descriptor into our new type */
454 MemoryDescriptor->MemoryType = MemoryType;
455 }
456 else
457 {
458 /* Get the current memory type of the descriptor, and reserve it */
459 CurrentType = MemoryDescriptor->MemoryType;
460 MemoryDescriptor->MemoryType = LoaderSpecialMemory;
461
462 /* Check if we'll need another descriptor for what's left of memory */
463 UseNext = ((BasePage != MemoryDescriptor->BasePage) &&
464 (Delta + PageCount != MemoryDescriptor->PageCount));
465
466 /* Get a descriptor */
467 Descriptor = ArmAllocateMemoryDescriptor();
468 if (!Descriptor) return STATUS_INSUFFICIENT_RESOURCES;
469
470 /* Check if we are using another descriptor */
471 if (UseNext)
472 {
473 /* Allocate that one too */
474 NextDescriptor = ArmAllocateMemoryDescriptor();
475 if (!NextDescriptor) return STATUS_INSUFFICIENT_RESOURCES;
476 }
477
478 /* Build the descriptor we got */
479 Descriptor->MemoryType = MemoryType;
480 Descriptor->BasePage = BasePage;
481 Descriptor->PageCount = PageCount;
482
483 /* Check if we're starting at the same place as the old one */
484 if (BasePage == MemoryDescriptor->BasePage)
485 {
486 /* Simply decrease the old descriptor and rebase it */
487 MemoryDescriptor->BasePage += PageCount;
488 MemoryDescriptor->PageCount -= PageCount;
489 MemoryDescriptor->MemoryType = CurrentType;
490 }
491 else if (Delta + PageCount == MemoryDescriptor->PageCount)
492 {
493 /* We finish where the old one did, shorten it */
494 MemoryDescriptor->PageCount -= PageCount;
495 MemoryDescriptor->MemoryType = CurrentType;
496 }
497 else
498 {
499 /* We're inside the current block, mark our free region */
500 NextDescriptor->MemoryType = LoaderFree;
501 NextDescriptor->BasePage = BasePage + PageCount;
502 NextDescriptor->PageCount = MemoryDescriptor->PageCount -
503 (PageCount + Delta);
504
505 /* And cut down the current descriptor */
506 MemoryDescriptor->PageCount = Delta;
507 MemoryDescriptor->MemoryType = CurrentType;
508
509 /* Finally, insert our new free descriptor into the list */
510 ArmInsertMemoryDescriptor(NextDescriptor);
511 }
512
513 /* Insert the descriptor we allocated */
514 ArmInsertMemoryDescriptor(Descriptor);
515 }
516
517 /* Return success */
518 return STATUS_SUCCESS;
519 }
520
521 PMEMORY_ALLOCATION_DESCRIPTOR
522 NTAPI
523 ArmFindMemoryDescriptor(IN ULONG BasePage)
524 {
525 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock = NULL;
526 PLIST_ENTRY NextEntry, ListHead;
527
528 /* Scan the memory descriptor list */
529 ListHead = &ArmLoaderBlock->MemoryDescriptorListHead;
530 NextEntry = ListHead->Flink;
531 while (NextEntry != ListHead)
532 {
533 /* Get the current descriptor */
534 MdBlock = CONTAINING_RECORD(NextEntry,
535 MEMORY_ALLOCATION_DESCRIPTOR,
536 ListEntry);
537
538 /* Check if it can contain our memory range */
539 if ((MdBlock->BasePage <= BasePage) &&
540 (MdBlock->BasePage + MdBlock->PageCount > BasePage))
541 {
542 /* It can, break out */
543 break;
544 }
545
546 /* Go to the next descriptor */
547 NextEntry = NextEntry->Flink;
548 }
549
550 /* Return the descriptor we found, if any */
551 return MdBlock;
552 }
553
554 NTSTATUS
555 NTAPI
556 ArmCreateMemoryDescriptor(IN TYPE_OF_MEMORY MemoryType,
557 IN ULONG BasePage,
558 IN ULONG PageCount,
559 IN ULONG Alignment,
560 OUT PULONG ReturnedBase)
561 {
562 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
563 ULONG AlignedBase, AlignedLimit;
564 PMEMORY_ALLOCATION_DESCRIPTOR ActiveMdBlock;
565 ULONG ActiveAlignedBase = 0;
566 PLIST_ENTRY NextEntry, ListHead;
567
568 /* If no information was given, make some assumptions */
569 if (!Alignment) Alignment = 1;
570 if (!PageCount) PageCount = 1;
571
572 /* Start looking for a matching descvriptor */
573 do
574 {
575 /* Calculate the limit of the range */
576 AlignedLimit = PageCount + BasePage;
577
578 /* Find a descriptor that already contains our base address */
579 MdBlock = ArmFindMemoryDescriptor(BasePage);
580 if (MdBlock)
581 {
582 /* If it contains our limit as well, break out early */
583 if ((MdBlock->PageCount + MdBlock->BasePage) >= AlignedLimit) break;
584 }
585
586 /* Loop the memory list */
587 AlignedBase = 0;
588 ActiveMdBlock = NULL;
589 ListHead = &ArmLoaderBlock->MemoryDescriptorListHead;
590 NextEntry = ListHead->Flink;
591 while (NextEntry != ListHead)
592 {
593 /* Get the current descriptors */
594 MdBlock = CONTAINING_RECORD(NextEntry,
595 MEMORY_ALLOCATION_DESCRIPTOR,
596 ListEntry);
597
598 /* Align the base address and our limit */
599 AlignedBase = (MdBlock->BasePage + (Alignment - 1)) &~ Alignment;
600 AlignedLimit = MdBlock->PageCount -
601 AlignedBase +
602 MdBlock->BasePage;
603
604 /* Check if this is a free block that can satisfy us */
605 if ((MdBlock->MemoryType == LoaderFree) &&
606 (AlignedLimit <= MdBlock->PageCount) &&
607 (PageCount <= AlignedLimit))
608 {
609 /* It is, stop searching */
610 ActiveMdBlock = MdBlock;
611 ActiveAlignedBase = AlignedBase;
612 break;
613 }
614
615 /* Try the next block */
616 NextEntry = NextEntry->Flink;
617 }
618
619 /* See if we came up with an adequate block */
620 if (ActiveMdBlock)
621 {
622 /* Generate a descriptor in it */
623 *ReturnedBase = AlignedBase;
624 return ArmBuildMemoryDescriptor(ActiveMdBlock,
625 MemoryType,
626 ActiveAlignedBase,
627 PageCount);
628 }
629 } while (TRUE);
630
631 /* We found a matching block, generate a descriptor with it */
632 *ReturnedBase = BasePage;
633 return ArmBuildMemoryDescriptor(MdBlock, MemoryType, BasePage, PageCount);
634 }
635
636 NTSTATUS
637 NTAPI
638 ArmBuildLoaderMemoryList(VOID)
639 {
640 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
641 MEMORY_DESCRIPTOR *Memory;
642 ULONG i;
643
644 /* Loop all BIOS Memory Descriptors */
645 for (i = 0; i < NumberDescriptors; i++)
646 {
647 /* Get the current descriptor */
648 Memory = &MDArray[i];
649
650 /* Allocate an NT Memory Descriptor */
651 Descriptor = ArmAllocateMemoryDescriptor();
652 if (!Descriptor) return ENOMEM;
653
654 /* Copy the memory type */
655 Descriptor->MemoryType = Memory->MemoryType;
656 if (Memory->MemoryType == MemoryFreeContiguous)
657 {
658 /* Convert this to free */
659 Descriptor->MemoryType = LoaderFree;
660 }
661 else if (Memory->MemoryType == MemorySpecialMemory)
662 {
663 /* Convert this to special memory */
664 Descriptor->MemoryType = LoaderSpecialMemory;
665 }
666
667 /* Copy the range data */
668 Descriptor->BasePage = Memory->BasePage;
669 Descriptor->PageCount = Memory->PageCount;
670
671 /* Insert the descriptor */
672 if (Descriptor->PageCount) ArmInsertMemoryDescriptor(Descriptor);
673 }
674
675 /* All went well */
676 return STATUS_SUCCESS;
677 }
678
679 #define PFN_SHIFT 12
680 #define LARGE_PFN_SHIFT 20
681
682 #define PTE_BASE 0xC0000000
683 #define PDE_BASE 0xC0400000
684 #define HAL_BASE 0xFFC00000
685 #define MMIO_BASE 0x10000000
686
687 #define LowMemPageTableIndex 0
688 #define StartupPtePageTableIndex (PTE_BASE >> PDE_SHIFT)
689 #define StartupPdePageTableIndex (PDE_BASE >> PDE_SHIFT)
690 #define MmioPageTableIndex (MMIO_BASE >> PDE_SHIFT)
691 #define HalPageTableIndex (HAL_BASE >> PDE_SHIFT)
692
693 /* Converts a Physical Address into a Page Frame Number */
694 #define PaToPfn(p) ((p) >> PFN_SHIFT)
695 #define PaToLargePfn(p) ((p) >> LARGE_PFN_SHIFT)
696 #define PaPtrToPfn(p) (((ULONG_PTR)(p)) >> PFN_SHIFT)
697
698 /* Converts a Physical Address into a Coarse Page Table PFN */
699 #define PaPtrToPdePfn(p) (((ULONG_PTR)(p)) >> CPT_SHIFT)
700
701 HARDWARE_PTE_ARMV6 TempPte;
702 HARDWARE_LARGE_PTE_ARMV6 TempLargePte;
703 HARDWARE_PDE_ARMV6 TempPde;
704
705 PVOID
706 ArmSetupPageDirectory(VOID)
707 {
708 PPAGE_DIRECTORY_ARM PageDir;
709 PPAGE_TABLE_ARM PageTable, KernelPageTable;
710 ULONG KernelPageTableIndex;
711 ULONG i;
712 PHARDWARE_PTE_ARMV6 PointerPte;
713 PHARDWARE_PDE_ARMV6 PointerPde;
714 PHARDWARE_LARGE_PTE_ARMV6 LargePte;
715 PFN_NUMBER Pfn;
716
717 /* Setup templates */
718 TempPte.Accessed = TempPte.Valid = TempLargePte.LargePage = TempLargePte.Accessed = TempPde.Valid = 1;
719
720 /* Get the Kernel Table Index */
721 KernelPageTableIndex = KernelBase >> PDE_SHIFT;
722
723 /* Allocate 1MB PDE_BASE and HYPER_SPACE. This will be improved later. Must be 1MB aligned */
724 PageDir = MmAllocateMemoryAtAddress(1 * 1024 * 1024, (PVOID)0x700000, LoaderMemoryData);
725
726 /* Setup the Low Memory PDE as an identity-mapped Large Page (1MB) */
727 LargePte = &PageDir->Pte[LowMemPageTableIndex];
728 *LargePte = TempLargePte;
729
730 /* Setup the MMIO PDE as two identity mapped large pages -- the kernel will blow these away later */
731 LargePte = &PageDir->Pte[MmioPageTableIndex];
732 Pfn = PaToLargePfn(0x10000000);
733 for (i = 0; i < 2; i++)
734 {
735 TempLargePte.PageFrameNumber = Pfn++;
736 *LargePte++ = TempLargePte;
737 }
738
739 /* Allocate 8 page tables (8KB) to describe the 8MB initial kernel region */
740 KernelPageTable = MmAllocateMemoryWithType(8192, LoaderMemoryData);
741
742 /* Setup the Kernel PDEs */
743 PointerPde = &PageDir->Pde[KernelPageTableIndex];
744 Pfn = PaPtrToPdePfn(KernelPageTable);
745 for (i = 0; i < 8; i++)
746 {
747 TempPde.PageFrameNumber = Pfn;
748 *PointerPde++ = TempPde;
749 Pfn++;
750 }
751
752 /* Setup the Kernel PTEs */
753 PointerPte = KernelPageTable->Pte;
754 Pfn = PaPtrToPfn(KERNEL_BASE_PHYS);
755 for (i = 0; i < 1536; i++)
756 {
757 TempPte.PageFrameNumber = Pfn++;
758 *PointerPte++ = TempPte;
759 }
760
761 /* Setup the Startup PDE */
762 LargePte = &PageDir->Pte[StartupPdePageTableIndex];
763 TempLargePte.PageFrameNumber = PaToLargePfn((ULONG_PTR)PageDir);
764 *LargePte = TempLargePte;
765
766 /* After this point, any MiAddressToPde is guaranteed not to fault */
767
768 /* Allocate 4 page tables (4KB) to describe the 4MB PTE_BASE region */
769 PageTable = MmAllocateMemoryWithType(4096, LoaderMemoryData);
770
771 /*
772 * Link them in the Startup PDE.
773 * Note these are the entries in the PD at (MiAddressToPde(PTE_BASE)).
774 */
775 PointerPde = &PageDir->Pde[StartupPtePageTableIndex];
776 Pfn = PaPtrToPdePfn(PageTable);
777 for (i = 0; i < 4; i++)
778 {
779 TempPde.PageFrameNumber = Pfn++;
780 *PointerPde++ = TempPde;
781 }
782
783 /*
784 * Now map these page tables in PTE space (MiAddressToPte(PTE_BASE)).
785 * Note that they all live on a single page, since each is 1KB.
786 */
787 PointerPte = &PageTable->Pte[0x300];
788 TempPte.PageFrameNumber = PaPtrToPfn(PageTable);
789 *PointerPte = TempPte;
790
791 /*
792 * After this point, MiAddressToPte((PDE_BASE) to MiAddressToPte(PDE_TOP))
793 * is guaranteed not to fault.
794 * Any subsequent page allocation will first need its page table created
795 * and mapped in the PTE_BASE first, then the page table itself will be
796 * editable through its flat PTE address.
797 */
798 return PageDir;
799 }
800
801 VOID
802 ArmSetupPagingAndJump(IN PVOID PageDirectoryBaseAddress)
803 {
804 ARM_CONTROL_REGISTER ControlRegister;
805 ARM_TTB_REGISTER TtbRegister;
806 ARM_DOMAIN_REGISTER DomainRegister;
807
808 /* Set the TTBR */
809 TtbRegister.AsUlong = (ULONG_PTR)PageDirectoryBaseAddress;
810 ASSERT(TtbRegister.Reserved == 0);
811 KeArmTranslationTableRegisterSet(TtbRegister);
812
813 /* Disable domains and simply use access bits on PTEs */
814 DomainRegister.AsUlong = 0;
815 DomainRegister.Domain0 = ClientDomain;
816 KeArmDomainRegisterSet(DomainRegister);
817
818 /* Enable ARMv6+ paging (MMU), caches and the access bit */
819 ControlRegister = KeArmControlRegisterGet();
820 ControlRegister.MmuEnabled = TRUE;
821 ControlRegister.ICacheEnabled = TRUE;
822 ControlRegister.DCacheEnabled = TRUE;
823 ControlRegister.ForceAp = TRUE;
824 ControlRegister.ExtendedPageTables = TRUE;
825 KeArmControlRegisterSet(ControlRegister);
826
827 /* Jump to Kernel */
828 (*KernelEntryPoint)((PVOID)((ULONG_PTR)ArmLoaderBlock | KSEG0_BASE));
829 }
830
831 VOID
832 ArmPrepareForReactOS(IN BOOLEAN Setup)
833 {
834 ARM_CACHE_REGISTER CacheReg;
835 PVOID Base, MemBase;
836 PCHAR BootPath, HalPath;
837 NTSTATUS Status;
838 ULONG Dummy, i;
839 PLDR_DATA_TABLE_ENTRY LdrEntry;
840 PLIST_ENTRY NextEntry, OldEntry;
841 PARC_DISK_INFORMATION ArcDiskInformation;
842 PARC_DISK_SIGNATURE ArcDiskSignature;
843 ULONG ArcDiskCount = 0;
844 #if 0
845 ULONG Checksum = 0;
846 PMASTER_BOOT_RECORD Mbr;
847 PULONG Buffer;
848 #endif
849 PWCHAR ArmModuleName;
850
851 //
852 // Allocate the ARM Shared Heap
853 //
854 ArmSharedHeap = MmAllocateMemoryWithType(PAGE_SIZE, LoaderOsloaderHeap);
855 ArmSharedHeapSize = 0;
856 if (!ArmSharedHeap) return;
857
858 //
859 // Allocate the loader block and extension
860 //
861 ArmLoaderBlock = ArmAllocateFromSharedHeap(sizeof(LOADER_PARAMETER_BLOCK));
862 if (!ArmLoaderBlock) return;
863 ArmExtension = ArmAllocateFromSharedHeap(sizeof(LOADER_PARAMETER_EXTENSION));
864 if (!ArmExtension) return;
865
866 //
867 // Initialize the loader block
868 //
869 InitializeListHead(&ArmLoaderBlock->BootDriverListHead);
870 InitializeListHead(&ArmLoaderBlock->LoadOrderListHead);
871 InitializeListHead(&ArmLoaderBlock->MemoryDescriptorListHead);
872
873 //
874 // Setup the extension and setup block
875 //
876 ArmLoaderBlock->Extension = (PVOID)((ULONG_PTR)ArmExtension | KSEG0_BASE);
877 ArmLoaderBlock->SetupLdrBlock = NULL;
878
879 //
880 // Add the Board Memory Map from U-Boot into the STARTUP.COM-style
881 // BIOS descriptor format -- this needs to be removed later.
882 //
883 ArmBuildBoardMemoryMap();
884
885 //
886 // Now basically convert these entries to the ARC format, so that we can
887 // get a good map of free (usable) memory
888 //
889 ArmBuildOsMemoryMap();
890
891 //
892 // NT uses an extended ARC format, with slightly different memory types.
893 // We also want to link the ARC descriptors together into a linked list,
894 // instead of the array, and allocate the semi-permanent storage in which
895 // these entries will be stored so that the kernel can read them.
896 //
897 ArmBuildLoaderMemoryList();
898
899 //
900 // Setup descriptor for the shared heap
901 //
902 Status = ArmCreateMemoryDescriptor(LoaderOsloaderHeap,
903 (ULONG_PTR)ArmSharedHeap >> PAGE_SHIFT,
904 ADDRESS_AND_SIZE_TO_SPAN_PAGES(ArmSharedHeap,
905 ArmSharedHeapSize),
906 0,
907 &Dummy);
908 if (Status != STATUS_SUCCESS) return;
909
910 //
911 // Setup descriptor for the boot stack
912 //
913 Status = ArmCreateMemoryDescriptor(LoaderOsloaderStack,
914 (ULONG_PTR)&BootStack >> PAGE_SHIFT,
915 4,
916 0,
917 &Dummy);
918 if (Status != STATUS_SUCCESS) return;
919 #if 0
920 //
921 // Setup descriptor for the boot page tables
922 //
923 Status = ArmCreateMemoryDescriptor(LoaderMemoryData,
924 (ULONG_PTR)&TranslationTableStart >> PAGE_SHIFT,
925 ((ULONG_PTR)&TranslationTableEnd -
926 (ULONG_PTR)&TranslationTableStart) / PAGE_SIZE,
927 0,
928 &Dummy);
929 if (Status != STATUS_SUCCESS) return;
930 #endif
931 //
932 // Setup descriptor for the kernel
933 //
934 Status = ArmCreateMemoryDescriptor(LoaderSystemCode,
935 KernelData >> PAGE_SHIFT,
936 ADDRESS_AND_SIZE_TO_SPAN_PAGES(KernelData,
937 KernelSize),
938 0,
939 &Dummy);
940 if (Status != STATUS_SUCCESS) return;
941
942 //
943 // Setup descriptor for the HAL
944 //
945 Status = ArmCreateMemoryDescriptor(LoaderHalCode,
946 HalData >> PAGE_SHIFT,
947 ADDRESS_AND_SIZE_TO_SPAN_PAGES(HalData,
948 HalSize),
949 0,
950 &Dummy);
951 if (Status != STATUS_SUCCESS) return;
952
953 //
954 // Setup registry data
955 //
956 ArmLoaderBlock->RegistryBase = (PVOID)((ULONG_PTR)RegistryData | KSEG0_BASE);
957 ArmLoaderBlock->RegistryLength = RegistrySize;
958
959 //
960 // Create an MD for it
961 //
962 Status = ArmCreateMemoryDescriptor(LoaderRegistryData,
963 RegistryData >> PAGE_SHIFT,
964 ADDRESS_AND_SIZE_TO_SPAN_PAGES(RegistryData,
965 RegistrySize),
966 0,
967 &Dummy);
968 if (Status != STATUS_SUCCESS) return;
969
970 //
971 // TODO: Setup ARC Hardware tree data
972 //
973
974 //
975 // Setup NLS data
976 //
977 ArmNlsDataBlock = ArmAllocateFromSharedHeap(sizeof(NLS_DATA_BLOCK));
978 ArmLoaderBlock->NlsData = ArmNlsDataBlock;
979 ArmLoaderBlock->NlsData->AnsiCodePageData = (PVOID)(AnsiData | KSEG0_BASE);
980 ArmLoaderBlock->NlsData->OemCodePageData = (PVOID)(OemData | KSEG0_BASE);
981 ArmLoaderBlock->NlsData->UnicodeCodePageData = (PVOID)(UnicodeData | KSEG0_BASE);
982 ArmLoaderBlock->NlsData = (PVOID)((ULONG_PTR)ArmLoaderBlock->NlsData | KSEG0_BASE);
983
984 //
985 // Setup ANSI NLS Memory Descriptor
986 //
987 Status = ArmCreateMemoryDescriptor(LoaderNlsData,
988 AnsiData >> PAGE_SHIFT,
989 ADDRESS_AND_SIZE_TO_SPAN_PAGES(AnsiData,
990 AnsiSize),
991 0,
992 &Dummy);
993 if (Status != STATUS_SUCCESS) return;
994
995 //
996 // Setup OEM NLS Memory Descriptor
997 //
998 Status = ArmCreateMemoryDescriptor(LoaderNlsData,
999 OemData >> PAGE_SHIFT,
1000 ADDRESS_AND_SIZE_TO_SPAN_PAGES(OemData,
1001 OemSize),
1002 0,
1003 &Dummy);
1004 if (Status != STATUS_SUCCESS) return;
1005
1006 //
1007 // Setup Unicode NLS Memory Descriptor
1008 //
1009 Status = ArmCreateMemoryDescriptor(LoaderNlsData,
1010 UnicodeData >> PAGE_SHIFT,
1011 ADDRESS_AND_SIZE_TO_SPAN_PAGES(UnicodeData,
1012 UnicodeSize),
1013 0,
1014 &Dummy);
1015 if (Status != STATUS_SUCCESS) return;
1016
1017 //
1018 // Setup loader entry for the kernel
1019 //
1020 ArmModuleName = ArmAllocateFromSharedHeap(64 * sizeof(WCHAR));
1021 wcscpy(ArmModuleName, L"ntoskrnl.exe");
1022 LdrEntry = ArmAllocateFromSharedHeap(sizeof(LDR_DATA_TABLE_ENTRY));
1023 RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
1024 LdrEntry->DllBase = (PVOID)KernelBase;
1025 LdrEntry->SizeOfImage = KernelSize;
1026 LdrEntry->EntryPoint = KernelEntryPoint;
1027 LdrEntry->LoadCount = 1;
1028 LdrEntry->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED;
1029 RtlInitUnicodeString(&LdrEntry->FullDllName, ArmModuleName);
1030 RtlInitUnicodeString(&LdrEntry->BaseDllName, ArmModuleName);
1031 LdrEntry->FullDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry->FullDllName.Buffer | KSEG0_BASE);
1032 LdrEntry->BaseDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry->BaseDllName.Buffer | KSEG0_BASE);
1033 InsertTailList(&ArmLoaderBlock->LoadOrderListHead, &LdrEntry->InLoadOrderLinks);
1034
1035 //
1036 // Setup loader entry for the HAL
1037 //
1038 ArmModuleName = ArmAllocateFromSharedHeap(64 * sizeof(WCHAR));
1039 wcscpy(ArmModuleName, L"hal.dll");
1040 LdrEntry = ArmAllocateFromSharedHeap(sizeof(LDR_DATA_TABLE_ENTRY));
1041 RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
1042 LdrEntry->DllBase = (PVOID)(HalData | KSEG0_BASE);
1043 LdrEntry->SizeOfImage = HalSize;
1044 LdrEntry->EntryPoint = (PVOID)RtlImageNtHeader((PVOID)HalData)->
1045 OptionalHeader.AddressOfEntryPoint;
1046 LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)LdrEntry->EntryPoint | KSEG0_BASE);
1047 LdrEntry->LoadCount = 1;
1048 LdrEntry->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED;
1049 RtlInitUnicodeString(&LdrEntry->FullDllName, ArmModuleName);
1050 RtlInitUnicodeString(&LdrEntry->BaseDllName, ArmModuleName);
1051 LdrEntry->FullDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry->FullDllName.Buffer | KSEG0_BASE);
1052 LdrEntry->BaseDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry->BaseDllName.Buffer | KSEG0_BASE);
1053 InsertTailList(&ArmLoaderBlock->LoadOrderListHead, &LdrEntry->InLoadOrderLinks);
1054
1055 //
1056 // Build descriptors for the drivers loaded
1057 //
1058 for (i = 0; i < Drivers; i++)
1059 {
1060 //
1061 // Setup loader entry for the driver
1062 //
1063 LdrEntry = ArmAllocateFromSharedHeap(sizeof(LDR_DATA_TABLE_ENTRY));
1064 RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
1065 LdrEntry->DllBase = (PVOID)(DriverData[i] | KSEG0_BASE);
1066 LdrEntry->SizeOfImage = DriverSize[i];
1067 LdrEntry->EntryPoint = (PVOID)RtlImageNtHeader((PVOID)DriverData[i])->
1068 OptionalHeader.AddressOfEntryPoint;
1069 LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)LdrEntry->EntryPoint | KSEG0_BASE);
1070 LdrEntry->LoadCount = 1;
1071 LdrEntry->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_PROCESSED;
1072 ArmModuleName = ArmAllocateFromSharedHeap(64 * sizeof(WCHAR));
1073 RtlZeroMemory(ArmModuleName, 64 * sizeof(WCHAR));
1074 LdrEntry->FullDllName.Length = strlen(DriverName[i]) * sizeof(WCHAR);
1075 LdrEntry->FullDllName.MaximumLength = LdrEntry->FullDllName.Length;
1076 LdrEntry->FullDllName.Buffer = ArmModuleName;
1077 LdrEntry->BaseDllName = LdrEntry->FullDllName;
1078 while (*DriverName[i]) *ArmModuleName++ = *DriverName[i]++;
1079 LdrEntry->FullDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry->FullDllName.Buffer | KSEG0_BASE);
1080 LdrEntry->BaseDllName.Buffer = (PVOID)((ULONG_PTR)LdrEntry->BaseDllName.Buffer | KSEG0_BASE);
1081 InsertTailList(&ArmLoaderBlock->LoadOrderListHead, &LdrEntry->InLoadOrderLinks);
1082
1083 //
1084 // Build a descriptor for the driver
1085 //
1086 Status = ArmCreateMemoryDescriptor(LoaderBootDriver,
1087 DriverData[i] >> PAGE_SHIFT,
1088 ADDRESS_AND_SIZE_TO_SPAN_PAGES(DriverData[i],
1089 DriverSize[i]),
1090 0,
1091 &Dummy);
1092 if (Status != STATUS_SUCCESS) return;
1093 }
1094
1095 //
1096 // Loop driver list
1097 //
1098 NextEntry = ArmLoaderBlock->LoadOrderListHead.Flink;
1099 while (NextEntry != &ArmLoaderBlock->LoadOrderListHead)
1100 {
1101 //
1102 // Remember the physical entry
1103 //
1104 OldEntry = NextEntry->Flink;
1105
1106 //
1107 // Edit the data
1108 //
1109 NextEntry->Flink = (PVOID)((ULONG_PTR)NextEntry->Flink | KSEG0_BASE);
1110 NextEntry->Blink = (PVOID)((ULONG_PTR)NextEntry->Blink | KSEG0_BASE);
1111
1112 //
1113 // Keep looping
1114 //
1115 NextEntry = OldEntry;
1116 }
1117
1118 //
1119 // Now edit the root itself
1120 //
1121 NextEntry->Flink = (PVOID)((ULONG_PTR)NextEntry->Flink | KSEG0_BASE);
1122 NextEntry->Blink = (PVOID)((ULONG_PTR)NextEntry->Blink | KSEG0_BASE);
1123
1124 //
1125 // Setup extension parameters
1126 //
1127 ArmExtension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
1128 ArmExtension->MajorVersion = 5;
1129 ArmExtension->MinorVersion = 2;
1130
1131 //
1132 // Make a copy of the command line
1133 //
1134 ArmLoaderBlock->LoadOptions = ArmCommandLine;
1135 strcpy(ArmCommandLine, reactos_kernel_cmdline);
1136
1137 //
1138 // Find the first \, separating the ARC path from NT path
1139 //
1140 BootPath = strchr(ArmCommandLine, '\\');
1141 *BootPath = ANSI_NULL;
1142
1143 //
1144 // Set the ARC Boot Path
1145 //
1146 strncpy(ArmArcBootPath, ArmCommandLine, 63);
1147 ArmLoaderBlock->ArcBootDeviceName = (PVOID)((ULONG_PTR)ArmArcBootPath | KSEG0_BASE);
1148
1149 //
1150 // The rest of the string is the NT path
1151 //
1152 HalPath = strchr(BootPath + 1, ' ');
1153 *HalPath = ANSI_NULL;
1154 ArmNtBootPath[0] = '\\';
1155 strncat(ArmNtBootPath, BootPath + 1, 63);
1156 strcat(ArmNtBootPath,"\\");
1157 ArmLoaderBlock->NtBootPathName = (PVOID)((ULONG_PTR)ArmNtBootPath | KSEG0_BASE);
1158
1159 //
1160 // Set the HAL paths
1161 //
1162 strncpy(ArmArcHalPath, ArmArcBootPath, 63);
1163 ArmLoaderBlock->ArcHalDeviceName = (PVOID)((ULONG_PTR)ArmArcHalPath | KSEG0_BASE);
1164 strcpy(ArmNtHalPath, "\\");
1165 ArmLoaderBlock->NtHalPathName = (PVOID)((ULONG_PTR)ArmNtHalPath | KSEG0_BASE);
1166
1167 //
1168 // Use this new command line
1169 //
1170 strncpy(ArmLoaderBlock->LoadOptions, HalPath + 2, 255);
1171
1172 //
1173 // Parse it and change every slash to a space
1174 //
1175 BootPath = ArmLoaderBlock->LoadOptions;
1176 do {if (*BootPath == '/') *BootPath = ' ';} while (*BootPath++);
1177
1178 //
1179 // Fixup command-line pointer
1180 //
1181 ArmLoaderBlock->LoadOptions = (PVOID)((ULONG_PTR)ArmLoaderBlock->LoadOptions | KSEG0_BASE);
1182
1183 //
1184 // Setup cache information
1185 //
1186 CacheReg = KeArmCacheRegisterGet();
1187 ArmLoaderBlock->u.Arm.FirstLevelDcacheSize = SizeBits[CacheReg.DSize];
1188 ArmLoaderBlock->u.Arm.FirstLevelDcacheFillSize = LenBits[CacheReg.DLength];
1189 ArmLoaderBlock->u.Arm.FirstLevelDcacheFillSize <<= 2;
1190 ArmLoaderBlock->u.Arm.FirstLevelIcacheSize = SizeBits[CacheReg.ISize];
1191 ArmLoaderBlock->u.Arm.FirstLevelIcacheFillSize = LenBits[CacheReg.ILength];
1192 ArmLoaderBlock->u.Arm.FirstLevelIcacheFillSize <<= 2;
1193 ArmLoaderBlock->u.Arm.SecondLevelDcacheSize =
1194 ArmLoaderBlock->u.Arm.SecondLevelDcacheFillSize =
1195 ArmLoaderBlock->u.Arm.SecondLevelIcacheSize =
1196 ArmLoaderBlock->u.Arm.SecondLevelIcacheFillSize = 0;
1197
1198 //
1199 // Allocate the Interrupt stack
1200 //
1201 Base = MmAllocateMemoryWithType(KERNEL_STACK_SIZE, LoaderStartupDpcStack);
1202 ArmLoaderBlock->u.Arm.InterruptStack = KSEG0_BASE | (ULONG)Base;
1203 ArmLoaderBlock->u.Arm.InterruptStack += KERNEL_STACK_SIZE;
1204
1205 //
1206 // Build an entry for it
1207 //
1208 Status = ArmCreateMemoryDescriptor(LoaderStartupDpcStack,
1209 (ULONG_PTR)Base >> PAGE_SHIFT,
1210 KERNEL_STACK_SIZE / PAGE_SIZE,
1211 0,
1212 &Dummy);
1213 if (Status != STATUS_SUCCESS) return;
1214
1215 //
1216 // Allocate the Kernel Boot stack
1217 //
1218 Base = MmAllocateMemoryWithType(KERNEL_STACK_SIZE, LoaderStartupKernelStack);
1219 ArmLoaderBlock->KernelStack = KSEG0_BASE | (ULONG)Base;
1220 ArmLoaderBlock->KernelStack += KERNEL_STACK_SIZE;
1221
1222 //
1223 // Build an entry for it
1224 //
1225 Status = ArmCreateMemoryDescriptor(LoaderStartupKernelStack,
1226 (ULONG_PTR)Base >> PAGE_SHIFT,
1227 KERNEL_STACK_SIZE / PAGE_SIZE,
1228 0,
1229 &Dummy);
1230 if (Status != STATUS_SUCCESS) return;
1231
1232 //
1233 // Allocate the Abort stack
1234 //
1235 Base = MmAllocateMemoryWithType(KERNEL_STACK_SIZE, LoaderStartupPanicStack);
1236 ArmLoaderBlock->u.Arm.PanicStack = KSEG0_BASE | (ULONG)Base;
1237 ArmLoaderBlock->u.Arm.PanicStack += KERNEL_STACK_SIZE;
1238
1239 //
1240 // Build an entry for it
1241 //
1242 Status = ArmCreateMemoryDescriptor(LoaderStartupPanicStack,
1243 (ULONG_PTR)Base >> PAGE_SHIFT,
1244 KERNEL_STACK_SIZE / PAGE_SIZE,
1245 0,
1246 &Dummy);
1247 if (Status != STATUS_SUCCESS) return;
1248
1249 //
1250 // Allocate the PCR/KUSER_SHARED page -- align it to 1MB (we only need 2x4KB)
1251 //
1252 Base = MmAllocateMemoryWithType(2 * 1024 * 1024, LoaderStartupPcrPage);
1253 MemBase = Base;
1254 Base = (PVOID)ROUND_UP(Base, 1 * 1024 * 1024);
1255 ArmLoaderBlock->u.Arm.PcrPage = (ULONG)Base >> PDE_SHIFT;
1256
1257 //
1258 // Build an entry for the KPCR and KUSER_SHARED_DATA
1259 //
1260 Status = ArmCreateMemoryDescriptor(LoaderStartupPcrPage,
1261 (ULONG_PTR)MemBase >> PAGE_SHIFT,
1262 (2 * 1024 * 1024) / PAGE_SIZE,
1263 0,
1264 &Dummy);
1265 if (Status != STATUS_SUCCESS) return;
1266
1267 //
1268 // Allocate PDR pages -- align them to 1MB (we only need 3x4KB)
1269 //
1270 Base = MmAllocateMemoryWithType(4 * 1024 * 1024, LoaderStartupPdrPage);
1271 MemBase = Base;
1272 Base = (PVOID)ROUND_UP(Base, 1 * 1024 * 1024);
1273 ArmLoaderBlock->u.Arm.PdrPage = (ULONG)Base >> PDE_SHIFT;
1274
1275 //
1276 // Build an entry for the PDR, PRCB and initial KPROCESS/KTHREAD
1277 //
1278 Status = ArmCreateMemoryDescriptor(LoaderStartupPdrPage,
1279 (ULONG_PTR)MemBase >> PAGE_SHIFT,
1280 (4 * 1024 * 1024) / PAGE_SIZE,
1281 0,
1282 &Dummy);
1283 if (Status != STATUS_SUCCESS) return;
1284
1285 //
1286 // Set initial PRCB, Thread and Process on the last PDR page
1287 //
1288 Base = (PVOID)((ULONG)Base + 2 * 1024 * 1024);
1289 ArmLoaderBlock->Prcb = KSEG0_BASE | (ULONG)Base;
1290 ArmLoaderBlock->Process = ArmLoaderBlock->Prcb + sizeof(KPRCB);
1291 ArmLoaderBlock->Thread = ArmLoaderBlock->Process + sizeof(EPROCESS);
1292
1293 //
1294 // Check if we're booting from RAM disk
1295 //
1296 if ((gRamDiskBase) && (gRamDiskSize))
1297 {
1298 //
1299 // Allocate a descriptor to describe it
1300 //
1301 Status = ArmCreateMemoryDescriptor(LoaderXIPRom,
1302 (ULONG_PTR)gRamDiskBase >> PAGE_SHIFT,
1303 gRamDiskSize / PAGE_SIZE,
1304 0,
1305 &Dummy);
1306 if (Status != STATUS_SUCCESS) return;
1307 }
1308
1309 //
1310 // Loop memory list
1311 //
1312 NextEntry = ArmLoaderBlock->MemoryDescriptorListHead.Flink;
1313 while (NextEntry != &ArmLoaderBlock->MemoryDescriptorListHead)
1314 {
1315 //
1316 // Remember the physical entry
1317 //
1318 OldEntry = NextEntry->Flink;
1319
1320 //
1321 // Edit the data
1322 //
1323 NextEntry->Flink = (PVOID)((ULONG_PTR)NextEntry->Flink | KSEG0_BASE);
1324 NextEntry->Blink = (PVOID)((ULONG_PTR)NextEntry->Blink | KSEG0_BASE);
1325
1326 //
1327 // Keep looping
1328 //
1329 NextEntry = OldEntry;
1330 }
1331
1332 //
1333 // Now edit the root itself
1334 //
1335 NextEntry->Flink = (PVOID)((ULONG_PTR)NextEntry->Flink | KSEG0_BASE);
1336 NextEntry->Blink = (PVOID)((ULONG_PTR)NextEntry->Blink | KSEG0_BASE);
1337
1338 //
1339 // Allocate ARC disk structure
1340 //
1341 ArcDiskInformation = ArmAllocateFromSharedHeap(sizeof(ARC_DISK_INFORMATION));
1342 InitializeListHead(&ArcDiskInformation->DiskSignatureListHead);
1343 ArmLoaderBlock->ArcDiskInformation = (PVOID)((ULONG_PTR)ArcDiskInformation | KSEG0_BASE);
1344
1345 #if 0
1346 //
1347 // Read the MBR
1348 //
1349 MachDiskReadLogicalSectors(0x49, 0ULL, 1, (PVOID)DISKREADBUFFER);
1350 Buffer = (ULONG*)DISKREADBUFFER;
1351 Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
1352
1353 //
1354 // Calculate the MBR checksum
1355 //
1356 for (i = 0; i < 128; i++) Checksum += Buffer[i];
1357 Checksum = ~Checksum + 1;
1358
1359 #endif
1360 //
1361 // Allocate a disk signature and fill it out
1362 //
1363 ArcDiskSignature = ArmAllocateFromSharedHeap(sizeof(ARC_DISK_SIGNATURE));
1364 ArcDiskSignature->Signature = 0xBADAB00B;// Mbr->Signature;
1365 ArcDiskSignature->CheckSum = 0xFAB4BEEF; //Checksum;
1366
1367 //
1368 // Allocare a string for the name and fill it out
1369 //
1370 ArcDiskSignature->ArcName = ArmAllocateFromSharedHeap(256);
1371 sprintf(ArcDiskSignature->ArcName, "multi(0)disk(0)rdisk(%lu)", ArcDiskCount++);
1372 ArcDiskSignature->ArcName = (PVOID)((ULONG_PTR)ArcDiskSignature->ArcName | KSEG0_BASE);
1373
1374 //
1375 // Insert the descriptor into the list
1376 //
1377 InsertTailList(&ArcDiskInformation->DiskSignatureListHead,
1378 &ArcDiskSignature->ListEntry);
1379
1380 //
1381 // Loop ARC disk list
1382 //
1383 NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
1384 while (NextEntry != &ArcDiskInformation->DiskSignatureListHead)
1385 {
1386 //
1387 // Remember the physical entry
1388 //
1389 OldEntry = NextEntry->Flink;
1390
1391 //
1392 // Edit the data
1393 //
1394 NextEntry->Flink = (PVOID)((ULONG_PTR)NextEntry->Flink | KSEG0_BASE);
1395 NextEntry->Blink = (PVOID)((ULONG_PTR)NextEntry->Blink | KSEG0_BASE);
1396
1397 //
1398 // Keep looping
1399 //
1400 NextEntry = OldEntry;
1401 }
1402
1403 //
1404 // Now edit the root itself
1405 //
1406 NextEntry->Flink = (PVOID)((ULONG_PTR)NextEntry->Flink | KSEG0_BASE);
1407 NextEntry->Blink = (PVOID)((ULONG_PTR)NextEntry->Blink | KSEG0_BASE);
1408 }
1409
1410 VOID
1411 FrLdrStartup(IN ULONG Magic)
1412 {
1413 PVOID PageDir;
1414 //
1415 // Disable interrupts (already done)
1416 //
1417
1418 //
1419 // Set proper CPSR (already done)
1420 //
1421
1422 //
1423 // Initialize the page directory
1424 //
1425 PageDir = ArmSetupPageDirectory();
1426
1427 //
1428 // Initialize paging and load NTOSKRNL
1429 //
1430 ArmSetupPagingAndJump(PageDir);
1431 }