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