d07cb3531557558b764fcb640be243e1c23c54d7
[reactos.git] / ntoskrnl / io / iomgr / ramdisk.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/io/iomgr/ramdisk.c
5 * PURPOSE: Allows booting from RAM disk
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #include <initguid.h>
13 #include <ntddrdsk.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 /* DATA ***********************************************************************/
18
19 #if defined (ALLOC_PRAGMA)
20 #pragma alloc_text(INIT, IopStartRamdisk)
21 #endif
22
23 /* FUNCTIONS ******************************************************************/
24
25 NTSTATUS
26 NTAPI
27 INIT_FUNCTION
28 IopStartRamdisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
29 {
30 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
31 NTSTATUS Status;
32 PCHAR CommandLine, Offset, OffsetValue, Length, LengthValue;
33 HANDLE DriverHandle;
34 RAMDISK_CREATE_INPUT RamdiskCreate;
35 IO_STATUS_BLOCK IoStatusBlock;
36 UNICODE_STRING GuidString, SymbolicLinkName, ObjectName, DeviceString;
37 PLIST_ENTRY ListHead, NextEntry;
38 OBJECT_ATTRIBUTES ObjectAttributes;
39 WCHAR SourceString[54];
40
41 //
42 // Scan memory descriptors
43 //
44 MemoryDescriptor = NULL;
45 ListHead = &LoaderBlock->MemoryDescriptorListHead;
46 NextEntry = ListHead->Flink;
47 while (NextEntry != ListHead)
48 {
49 //
50 // Get the descriptor
51 //
52 MemoryDescriptor = CONTAINING_RECORD(NextEntry,
53 MEMORY_ALLOCATION_DESCRIPTOR,
54 ListEntry);
55
56 //
57 // Needs to be a ROM/RAM descriptor
58 //
59 if (MemoryDescriptor->MemoryType == LoaderXIPRom) break;
60
61 //
62 // Keep trying
63 //
64 NextEntry = NextEntry->Flink;
65 }
66
67 //
68 // Nothing found?
69 //
70 if (NextEntry == ListHead)
71 {
72 //
73 // Bugcheck -- no data
74 //
75 KeBugCheckEx(RAMDISK_BOOT_INITIALIZATION_FAILED,
76 RD_NO_XIPROM_DESCRIPTOR,
77 STATUS_INVALID_PARAMETER,
78 0,
79 0);
80 }
81
82 //
83 // Setup the input buffer
84 //
85 RtlZeroMemory(&RamdiskCreate, sizeof(RamdiskCreate));
86 RamdiskCreate.Version = sizeof(RamdiskCreate);
87 RamdiskCreate.DiskType = RAMDISK_BOOT_DISK;
88 RamdiskCreate.BasePage = MemoryDescriptor->BasePage;
89 RamdiskCreate.DiskOffset = 0;
90 RamdiskCreate.DiskLength.QuadPart = MemoryDescriptor->PageCount << PAGE_SHIFT;
91 RamdiskCreate.DiskGuid = RAMDISK_BOOTDISK_GUID;
92 RamdiskCreate.DriveLetter = L'C';
93 RamdiskCreate.Options.Fixed = TRUE;
94
95 //
96 // Check for commandline parameters
97 //
98 CommandLine = LoaderBlock->LoadOptions;
99 if (CommandLine)
100 {
101 //
102 // Make everything upper case
103 //
104 _strupr(CommandLine);
105
106 //
107 // Check for offset parameter
108 //
109 Offset = strstr(CommandLine, "RDIMAGEOFFSET");
110 if (Offset)
111 {
112 //
113 // Get to the actual value
114 //
115 OffsetValue = strstr(Offset, "=");
116 if (OffsetValue)
117 {
118 //
119 // Set the offset
120 //
121 RamdiskCreate.DiskOffset = atol(OffsetValue + 1);
122 }
123 }
124
125 //
126 // Reduce the disk length
127 //
128 RamdiskCreate.DiskLength.QuadPart -= RamdiskCreate.DiskOffset;
129
130 //
131 // Check for length parameter
132 //
133 Length = strstr(CommandLine, "RDIMAGELENGTH");
134 if (Length)
135 {
136 //
137 // Get to the actual value
138 //
139 LengthValue = strstr(Length, "=");
140 if (LengthValue)
141 {
142 //
143 // Set the offset
144 //
145 RamdiskCreate.DiskLength.QuadPart = _atoi64(LengthValue + 1);
146 }
147 }
148 }
149
150 //
151 // Setup object attributes
152 //
153 RtlInitUnicodeString(&ObjectName, L"\\Device\\Ramdisk");
154 InitializeObjectAttributes(&ObjectAttributes,
155 &ObjectName,
156 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
157 NULL,
158 NULL);
159
160 //
161 // Open a handle to the driver
162 //
163 Status = ZwOpenFile(&DriverHandle,
164 GENERIC_ALL | SYNCHRONIZE,
165 &ObjectAttributes,
166 &IoStatusBlock,
167 FILE_SHARE_READ | FILE_SHARE_WRITE,
168 FILE_SYNCHRONOUS_IO_NONALERT);
169 if (!(NT_SUCCESS(Status)) || !(NT_SUCCESS(IoStatusBlock.Status)))
170 {
171 //
172 // Bugcheck -- no driver
173 //
174 KeBugCheckEx(RAMDISK_BOOT_INITIALIZATION_FAILED,
175 RD_NO_RAMDISK_DRIVER,
176 IoStatusBlock.Status,
177 0,
178 0);
179 }
180
181 //
182 // Send create command
183 //
184 Status = ZwDeviceIoControlFile(DriverHandle,
185 NULL,
186 NULL,
187 NULL,
188 &IoStatusBlock,
189 FSCTL_CREATE_RAM_DISK,
190 &RamdiskCreate,
191 sizeof(RamdiskCreate),
192 NULL,
193 0);
194 ZwClose(DriverHandle);
195 if (!(NT_SUCCESS(Status)) || !(NT_SUCCESS(IoStatusBlock.Status)))
196 {
197 //
198 // Bugcheck -- driver failed
199 //
200 KeBugCheckEx(RAMDISK_BOOT_INITIALIZATION_FAILED,
201 RD_FSCTL_FAILED,
202 IoStatusBlock.Status,
203 0,
204 0);
205 }
206
207 //
208 // Convert the GUID
209 //
210 Status = RtlStringFromGUID(&RamdiskCreate.DiskGuid, &GuidString);
211 if (!NT_SUCCESS(Status))
212 {
213 //
214 // Bugcheck -- GUID convert failed
215 //
216 KeBugCheckEx(RAMDISK_BOOT_INITIALIZATION_FAILED,
217 RD_GUID_CONVERT_FAILED,
218 Status,
219 0,
220 0);
221 }
222
223 //
224 // Build the symbolic link name and target
225 //
226 _snwprintf(SourceString,
227 sizeof(SourceString)/sizeof(WCHAR),
228 L"\\Device\\Ramdisk%wZ",
229 &GuidString);
230 SymbolicLinkName.Length = 38;
231 SymbolicLinkName.MaximumLength = 38 + sizeof(UNICODE_NULL);
232 SymbolicLinkName.Buffer = L"\\ArcName\\ramdisk(0)";
233
234 //
235 // Create the symbolic link
236 //
237 RtlInitUnicodeString(&DeviceString, SourceString);
238 Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceString);
239 RtlFreeUnicodeString(&GuidString);
240 if (!NT_SUCCESS(Status))
241 {
242 //
243 // Bugcheck -- symlink create failed
244 //
245 KeBugCheckEx(RAMDISK_BOOT_INITIALIZATION_FAILED,
246 RD_SYMLINK_CREATE_FAILED,
247 Status,
248 0,
249 0);
250 }
251
252 //
253 // We made it
254 //
255 return STATUS_SUCCESS;
256 }