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