Merging r37048, r37051, r37052, r37055 from the-real-msvc branch
[reactos.git] / reactos / boot / freeldr / freeldr / disk / ramdisk.c
1 /*
2 * PROJECT: ReactOS Boot Loader
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/freeldr/arch/i386/ramdisk.c
5 * PURPOSE: Implements routines to support booting from a RAM Disk
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <freeldr.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 PVOID gRamDiskBase;
18 ULONG gRamDiskSize;
19 extern BOOLEAN gCacheEnabled;
20
21 /* FUNCTIONS ******************************************************************/
22
23 FORCEINLINE
24 PVOID
25 RamDiskGetDataAtOffset(IN PVOID Offset)
26 {
27 //
28 // Return data from our RAM Disk
29 //
30 ASSERT(((ULONG_PTR)gRamDiskBase + (ULONG_PTR)Offset) <
31 ((ULONG_PTR)gRamDiskBase + (ULONG_PTR)gRamDiskSize));
32 return (PVOID)((ULONG_PTR)gRamDiskBase + (ULONG_PTR)(Offset));
33 }
34
35 ULONG
36 RamDiskGetCacheableBlockCount(IN ULONG Reserved)
37 {
38 //
39 // Allow 32KB transfers (64 sectors), emulating BIOS LBA
40 //
41 ASSERT(Reserved == 0x49);
42 return 64;
43 }
44
45 BOOLEAN
46 RamDiskGetDriveGeometry(IN ULONG Reserved,
47 OUT PGEOMETRY Geometry)
48 {
49 //
50 // Should never be called when the caller expects valid Geometry!
51 //
52 ASSERT(Reserved == 0x49);
53 return TRUE;
54 }
55
56 BOOLEAN
57 RamDiskReadLogicalSectors(IN ULONG Reserved,
58 IN ULONGLONG SectorNumber,
59 IN ULONG SectorCount,
60 IN PVOID Buffer)
61 {
62 PVOID StartAddress;
63 ULONG Length;
64 ASSERT(Reserved == 0x49);
65
66 //
67 // Get actual pointers and lengths
68 //
69 StartAddress = (PVOID)((ULONG_PTR)SectorNumber * 512);
70 Length = SectorCount * 512;
71
72 //
73 // Don't allow reads past our image
74 //
75 if (((ULONG_PTR)StartAddress + Length) > gRamDiskSize) return FALSE;
76
77 //
78 // Do the read
79 //
80 RtlCopyMemory(Buffer, RamDiskGetDataAtOffset(StartAddress), Length);
81 return TRUE;
82 }
83
84 VOID
85 NTAPI
86 RamDiskLoadVirtualFile(IN PCHAR FileName)
87 {
88 PFILE RamFile;
89 ULONG TotalRead, ChunkSize;
90 PCHAR MsgBuffer = "Loading ramdisk...";
91 ULONG PercentPerChunk, Percent;
92
93 //
94 // Display progress
95 //
96 UiDrawProgressBarCenter(1, 100, MsgBuffer);
97
98 //
99 // Try opening the ramdisk file (this assumes the boot volume was opened)
100 //
101 RamFile = FsOpenFile(FileName);
102 if (RamFile)
103 {
104 //
105 // Get the file size
106 //
107 gRamDiskSize = FsGetFileSize(RamFile);
108 if (!gRamDiskSize) return;
109
110 //
111 // Allocate memory for it
112 //
113 ChunkSize = 8 * 1024 * 1024;
114 Percent = PercentPerChunk = 100 / (gRamDiskSize / ChunkSize);
115 gRamDiskBase = MmAllocateMemory(gRamDiskSize);
116 if (!gRamDiskBase) return;
117
118 //
119 // Read it in chunks
120 //
121 for (TotalRead = 0; TotalRead < gRamDiskSize; TotalRead += ChunkSize)
122 {
123 //
124 // Check if we're at the last chunk
125 //
126 if ((gRamDiskSize - TotalRead) < ChunkSize)
127 {
128 //
129 // Only need the actual data required
130 //
131 ChunkSize = gRamDiskSize - TotalRead;
132 }
133
134 //
135 // Draw progress
136 //
137 UiDrawProgressBarCenter(Percent, 100, MsgBuffer);
138 Percent += PercentPerChunk;
139
140 //
141 // Copy the contents
142 //
143
144 if (!FsReadFile(RamFile,
145 ChunkSize,
146 NULL,
147 (PVOID)((ULONG_PTR)gRamDiskBase + TotalRead)))
148 {
149 //
150 // Fail
151 //
152 UiMessageBox("Failed to read ramdisk\n");
153 }
154 }
155 }
156 }
157
158 VOID
159 NTAPI
160 RamDiskSwitchFromBios(VOID)
161 {
162 extern ULONG BootDrive, BootPartition;
163
164 //
165 // Check if we have a ramdisk, in which case we need to switch routines
166 //
167 if (gRamDiskBase)
168 {
169 //
170 // Don't use the BIOS for reads anymore
171 //
172 MachVtbl.DiskReadLogicalSectors = RamDiskReadLogicalSectors;
173 MachVtbl.DiskGetDriveGeometry = RamDiskGetDriveGeometry;
174 MachVtbl.DiskGetCacheableBlockCount = RamDiskGetCacheableBlockCount;
175
176 //
177 // Also disable cached FAT reads
178 //
179 gCacheEnabled = FALSE;
180
181 //
182 // Switch to ramdisk boot partition
183 //
184 BootDrive = 0x49;
185 BootPartition = 0;
186 }
187 }