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