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