00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014
00015
00016
00017 typedef struct _DISK_INFORMATION
00018 {
00019 PDEVICE_OBJECT DeviceObject;
00020 ULONG SectorSize;
00021 DISK_GEOMETRY_EX DiskGeometry;
00022 PUSHORT Buffer;
00023 ULONGLONG SectorCount;
00024 } DISK_INFORMATION, *PDISK_INFORMATION;
00025
00026 #include <pshpack1.h>
00027 typedef struct _EFI_PARTITION_HEADER
00028 {
00029 ULONGLONG Signature;
00030 ULONG Revision;
00031 ULONG HeaderSize;
00032 ULONG HeaderCRC32;
00033 ULONG Reserved;
00034 ULONGLONG MyLBA;
00035 ULONGLONG AlternateLBA;
00036 ULONGLONG FirstUsableLBA;
00037 ULONGLONG LastUsableLBA;
00038 GUID DiskGUID;
00039 ULONGLONG PartitionEntryLBA;
00040 ULONG NumberOfEntries;
00041 ULONG SizeOfPartitionEntry;
00042 ULONG PartitionEntryCRC32;
00043 } EFI_PARTITION_HEADER, *PEFI_PARTITION_HEADER;
00044 #include <poppack.h>
00045
00046 typedef struct _EFI_PARTITION_ENTRY
00047 {
00048 GUID PartitionType;
00049 GUID UniquePartition;
00050 ULONGLONG StartingLBA;
00051 ULONGLONG EndingLBA;
00052 ULONGLONG Attributes;
00053 WCHAR Name[0x24];
00054 } EFI_PARTITION_ENTRY, *PEFI_PARTITION_ENTRY;
00055
00056 typedef struct _PARTITION_TABLE_ENTRY
00057 {
00058 UCHAR BootIndicator;
00059 UCHAR StartHead;
00060 UCHAR StartSector;
00061 UCHAR StartCylinder;
00062 UCHAR SystemIndicator;
00063 UCHAR EndHead;
00064 UCHAR EndSector;
00065 UCHAR EndCylinder;
00066 ULONG SectorCountBeforePartition;
00067 ULONG PartitionSectorCount;
00068 } PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY;
00069
00070 typedef struct _MASTER_BOOT_RECORD
00071 {
00072 UCHAR MasterBootRecordCodeAndData[0x1B8];
00073 ULONG Signature;
00074 USHORT Reserved;
00075 PARTITION_TABLE_ENTRY PartitionTable[4];
00076 USHORT MasterBootRecordMagic;
00077 } MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD;
00078
00079
00080 #define TAG_FSTUB 'BtsF'
00081
00082 #define PARTITION_ENTRY_SIZE 128
00083
00084 #define EFI_HEADER_SIGNATURE 0x5452415020494645ULL
00085
00086 #define EFI_HEADER_REVISION_1 0x00010000
00087
00088 #define EFI_PMBR_OSTYPE_EFI 0xEE
00089
00090 #define IS_VALID_DISK_INFO(Disk) \
00091 (Disk) && \
00092 (Disk->DeviceObject) && \
00093 (Disk->SectorSize) && \
00094 (Disk->Buffer) && \
00095 (Disk->SectorCount)
00096
00097 VOID
00098 NTAPI
00099 FstubDbgPrintPartitionEx(IN PPARTITION_INFORMATION_EX PartitionEntry,
00100 IN ULONG PartitionNumber
00101 );
00102
00103 NTSTATUS
00104 NTAPI
00105 FstubDetectPartitionStyle(IN PDISK_INFORMATION Disk,
00106 IN PARTITION_STYLE * PartitionStyle
00107 );
00108
00109 VOID
00110 NTAPI
00111 FstubFreeDiskInformation(IN PDISK_INFORMATION DiskBuffer
00112 );
00113
00114 NTSTATUS
00115 NTAPI
00116 FstubGetDiskGeometry(IN PDEVICE_OBJECT DeviceObject,
00117 OUT PDISK_GEOMETRY_EX Geometry
00118 );
00119
00120 NTSTATUS
00121 NTAPI
00122 FstubReadSector(IN PDEVICE_OBJECT DeviceObject,
00123 IN ULONG SectorSize,
00124 IN ULONGLONG StartingSector OPTIONAL,
00125 OUT PUSHORT Buffer
00126 );
00127
00128 NTSTATUS
00129 NTAPI
00130 FstubWriteBootSectorEFI(IN PDISK_INFORMATION Disk
00131 );
00132
00133 NTSTATUS
00134 NTAPI
00135 FstubWritePartitionTableEFI(IN PDISK_INFORMATION Disk,
00136 IN GUID DiskGUID,
00137 IN ULONG MaxPartitionCount,
00138 IN ULONGLONG FirstUsableLBA,
00139 IN ULONGLONG LastUsableLBA,
00140 IN BOOLEAN WriteBackupTable,
00141 IN ULONG PartitionCount,
00142 IN PPARTITION_INFORMATION_EX PartitionEntries OPTIONAL
00143 );
00144
00145 NTSTATUS
00146 NTAPI
00147 FstubWriteSector(IN PDEVICE_OBJECT DeviceObject,
00148 IN ULONG SectorSize,
00149 IN ULONGLONG StartingSector OPTIONAL,
00150 IN PUSHORT Buffer
00151 );
00152
00153 VOID
00154 NTAPI
00155 FstubAdjustPartitionCount(IN ULONG SectorSize,
00156 IN OUT PULONG PartitionCount)
00157 {
00158 ULONG Count;
00159 PAGED_CODE();
00160
00161 ASSERT(SectorSize);
00162 ASSERT(PartitionCount);
00163
00164
00165 Count = *PartitionCount;
00166
00167 if (Count < 128)
00168 {
00169 Count = 128;
00170 }
00171
00172
00173
00174
00175
00176 Count = (Count * PARTITION_ENTRY_SIZE) / SectorSize;
00177 Count = (Count * SectorSize) / PARTITION_ENTRY_SIZE;
00178 ASSERT(*PartitionCount <= Count);
00179
00180 *PartitionCount = Count;
00181
00182
00183 if (SectorSize == 512)
00184 {
00185 ASSERT(Count % 4 == 0);
00186 }
00187 }
00188
00189 NTSTATUS
00190 NTAPI
00191 FstubAllocateDiskInformation(IN PDEVICE_OBJECT DeviceObject,
00192 OUT PDISK_INFORMATION * DiskBuffer,
00193 PDISK_GEOMETRY_EX DiskGeometry OPTIONAL)
00194 {
00195 NTSTATUS Status;
00196 PDISK_INFORMATION DiskInformation;
00197 PAGED_CODE();
00198
00199 ASSERT(DeviceObject);
00200 ASSERT(DiskBuffer);
00201
00202
00203 DiskInformation = ExAllocatePoolWithTag(NonPagedPool, sizeof(DISK_INFORMATION), TAG_FSTUB);
00204 if (!DiskInformation)
00205 {
00206 return STATUS_INSUFFICIENT_RESOURCES;
00207 }
00208
00209
00210 if (!DiskGeometry)
00211 {
00212 Status = FstubGetDiskGeometry(DeviceObject, &(DiskInformation->DiskGeometry));
00213 if (!NT_SUCCESS(Status))
00214 {
00215 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
00216 return Status;
00217 }
00218 }
00219 else
00220 {
00221 DiskInformation->DiskGeometry = *DiskGeometry;
00222 }
00223
00224
00225 if (DiskInformation->DiskGeometry.Geometry.BytesPerSector == 0 ||
00226 DiskInformation->DiskGeometry.DiskSize.QuadPart == 0)
00227 {
00228 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
00229 return STATUS_DEVICE_NOT_READY;
00230 }
00231
00232
00233 DiskInformation->DeviceObject = DeviceObject;
00234 DiskInformation->SectorSize = DiskInformation->DiskGeometry.Geometry.BytesPerSector;
00235 DiskInformation->SectorCount = DiskInformation->DiskGeometry.DiskSize.QuadPart / DiskInformation->SectorSize;
00236
00237
00238 DiskInformation->Buffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, DiskInformation->SectorSize, TAG_FSTUB);
00239 if (!DiskInformation->Buffer)
00240 {
00241 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
00242 return STATUS_INSUFFICIENT_RESOURCES;
00243 }
00244
00245
00246 *DiskBuffer = DiskInformation;
00247
00248 return STATUS_SUCCESS;
00249 }
00250
00251 PDRIVE_LAYOUT_INFORMATION
00252 NTAPI
00253 FstubConvertExtendedToLayout(IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
00254 {
00255 ULONG i;
00256 PDRIVE_LAYOUT_INFORMATION DriveLayout;
00257 PAGED_CODE();
00258
00259 ASSERT(LayoutEx);
00260
00261
00262 if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR)
00263 {
00264 ASSERT(FALSE);
00265 return NULL;
00266 }
00267
00268
00269 DriveLayout = ExAllocatePoolWithTag(NonPagedPool,
00270 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry) +
00271 LayoutEx->PartitionCount * sizeof(PARTITION_INFORMATION),
00272 TAG_FSTUB);
00273 if (!DriveLayout)
00274 {
00275 return NULL;
00276 }
00277
00278
00279 DriveLayout->PartitionCount = LayoutEx->PartitionCount;
00280 DriveLayout->Signature = LayoutEx->Mbr.Signature;
00281
00282
00283 for (i = 0; i < LayoutEx->PartitionCount; i++)
00284 {
00285 DriveLayout->PartitionEntry[i].StartingOffset = LayoutEx->PartitionEntry[i].StartingOffset;
00286 DriveLayout->PartitionEntry[i].PartitionLength = LayoutEx->PartitionEntry[i].PartitionLength;
00287 DriveLayout->PartitionEntry[i].HiddenSectors = LayoutEx->PartitionEntry[i].Mbr.HiddenSectors;
00288 DriveLayout->PartitionEntry[i].PartitionNumber = LayoutEx->PartitionEntry[i].PartitionNumber;
00289 DriveLayout->PartitionEntry[i].PartitionType = LayoutEx->PartitionEntry[i].Mbr.PartitionType;
00290 DriveLayout->PartitionEntry[i].BootIndicator = LayoutEx->PartitionEntry[i].Mbr.BootIndicator;
00291 DriveLayout->PartitionEntry[i].RecognizedPartition = LayoutEx->PartitionEntry[i].Mbr.RecognizedPartition;
00292 DriveLayout->PartitionEntry[i].RewritePartition = LayoutEx->PartitionEntry[i].RewritePartition;
00293 }
00294
00295 return DriveLayout;
00296 }
00297
00298 VOID
00299 NTAPI
00300 FstubCopyEntryEFI(OUT PEFI_PARTITION_ENTRY Entry,
00301 IN PPARTITION_INFORMATION_EX Partition,
00302 ULONG SectorSize)
00303 {
00304 PAGED_CODE();
00305
00306 ASSERT(Entry);
00307 ASSERT(Partition);
00308 ASSERT(SectorSize);
00309
00310
00311 Entry->PartitionType = Partition->Gpt.PartitionType;
00312 Entry->UniquePartition = Partition->Gpt.PartitionId;
00313 Entry->StartingLBA = Partition->StartingOffset.QuadPart / SectorSize;
00314 Entry->EndingLBA = (Partition->StartingOffset.QuadPart + Partition->PartitionLength.QuadPart - 1) / SectorSize;
00315 Entry->Attributes = Partition->Gpt.Attributes;
00316 RtlCopyMemory(Entry->Name, Partition->Gpt.Name, sizeof(Entry->Name));
00317 }
00318
00319 NTSTATUS
00320 NTAPI
00321 FstubCreateDiskMBR(IN PDEVICE_OBJECT DeviceObject,
00322 IN PCREATE_DISK_MBR DiskInfo)
00323 {
00324 NTSTATUS Status;
00325 PDISK_INFORMATION Disk = NULL;
00326 PMASTER_BOOT_RECORD MasterBootRecord;
00327 PAGED_CODE();
00328
00329 ASSERT(DeviceObject);
00330
00331
00332 Status = FstubAllocateDiskInformation(DeviceObject, &Disk, 0);
00333 if (!NT_SUCCESS(Status))
00334 {
00335 return Status;
00336 }
00337
00338
00339 Status = FstubReadSector(Disk->DeviceObject,
00340 Disk->SectorSize,
00341 0ULL,
00342 Disk->Buffer);
00343 if (!NT_SUCCESS(Status))
00344 {
00345 FstubFreeDiskInformation(Disk);
00346 return Status;
00347 }
00348
00349 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
00350 MasterBootRecord->Signature = DiskInfo->Signature;
00351 RtlZeroMemory(MasterBootRecord->PartitionTable, sizeof(PARTITION_TABLE_ENTRY) * 4);
00352 MasterBootRecord->MasterBootRecordMagic = BOOT_RECORD_SIGNATURE;
00353
00354
00355 Status = FstubWriteSector(Disk->DeviceObject,
00356 Disk->SectorSize,
00357 0ULL,
00358 Disk->Buffer);
00359
00360
00361 FstubFreeDiskInformation(Disk);
00362 return Status;
00363 }
00364
00365 NTSTATUS
00366 NTAPI
00367 FstubCreateDiskEFI(IN PDEVICE_OBJECT DeviceObject,
00368 IN PCREATE_DISK_GPT DiskInfo)
00369 {
00370 NTSTATUS Status;
00371 PDISK_INFORMATION Disk = NULL;
00372 ULONGLONG FirstUsableLBA, LastUsableLBA;
00373 ULONG MaxPartitionCount, SectorsForPartitions;
00374 PAGED_CODE();
00375
00376 ASSERT(DeviceObject);
00377 ASSERT(DiskInfo);
00378
00379
00380 Status = FstubAllocateDiskInformation(DeviceObject, &Disk, 0);
00381 if (!NT_SUCCESS(Status))
00382 {
00383 return Status;
00384 }
00385 ASSERT(Disk);
00386
00387
00388 Status = FstubWriteBootSectorEFI(Disk);
00389 if (!NT_SUCCESS(Status))
00390 {
00391 FstubFreeDiskInformation(Disk);
00392 return Status;
00393 }
00394
00395
00396 MaxPartitionCount = DiskInfo->MaxPartitionCount;
00397 FstubAdjustPartitionCount(Disk->SectorSize, &MaxPartitionCount);
00398
00399
00400 SectorsForPartitions = (MaxPartitionCount * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
00401
00402 FirstUsableLBA = SectorsForPartitions + 2;
00403
00404 LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
00405
00406
00407 Status = FstubWritePartitionTableEFI(Disk,
00408 DiskInfo->DiskId,
00409 MaxPartitionCount,
00410 FirstUsableLBA,
00411 LastUsableLBA,
00412 FALSE,
00413 0,
00414 NULL);
00415
00416 if (NT_SUCCESS(Status))
00417 {
00418 Status = FstubWritePartitionTableEFI(Disk,
00419 DiskInfo->DiskId,
00420 MaxPartitionCount,
00421 FirstUsableLBA,
00422 LastUsableLBA,
00423 TRUE,
00424 0,
00425 NULL);
00426 }
00427
00428
00429 FstubFreeDiskInformation(Disk);
00430 return Status;
00431 }
00432
00433 NTSTATUS
00434 NTAPI
00435 FstubCreateDiskRaw(IN PDEVICE_OBJECT DeviceObject)
00436 {
00437 NTSTATUS Status;
00438 PDISK_INFORMATION Disk = NULL;
00439 PARTITION_STYLE PartitionStyle;
00440 PMASTER_BOOT_RECORD MasterBootRecord;
00441 PAGED_CODE();
00442
00443 ASSERT(DeviceObject);
00444
00445
00446 Status = FstubAllocateDiskInformation(DeviceObject, &Disk, 0);
00447 if (!NT_SUCCESS(Status))
00448 {
00449 return Status;
00450 }
00451
00452
00453 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
00454 if (!NT_SUCCESS(Status))
00455 {
00456 FstubFreeDiskInformation(Disk);
00457 return Status;
00458 }
00459
00460
00461 Status = FstubReadSector(Disk->DeviceObject,
00462 Disk->SectorSize,
00463 0ULL,
00464 Disk->Buffer);
00465 if (!NT_SUCCESS(Status))
00466 {
00467 FstubFreeDiskInformation(Disk);
00468 return Status;
00469 }
00470
00471
00472 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
00473 MasterBootRecord->Signature = 0;
00474 RtlZeroMemory(MasterBootRecord->PartitionTable, sizeof(PARTITION_TABLE_ENTRY));
00475 MasterBootRecord->MasterBootRecordMagic = 0;
00476
00477
00478 Status = FstubWriteSector(Disk->DeviceObject,
00479 Disk->SectorSize,
00480 0ULL,
00481 Disk->Buffer);
00482
00483 if (PartitionStyle != PARTITION_STYLE_GPT)
00484 {
00485 FstubFreeDiskInformation(Disk);
00486 return Status;
00487 }
00488
00489
00490 RtlZeroMemory(Disk->Buffer, Disk->SectorSize);
00491
00492 Status = FstubWriteSector(Disk->DeviceObject,
00493 Disk->SectorSize,
00494 1ULL,
00495 Disk->Buffer);
00496
00497 if (NT_SUCCESS(Status))
00498 {
00499 Status = FstubWriteSector(Disk->DeviceObject,
00500 Disk->SectorSize,
00501 Disk->SectorCount - 1ULL,
00502 Disk->Buffer);
00503 }
00504
00505
00506 FstubFreeDiskInformation(Disk);
00507 return Status;
00508 }
00509
00510 PCHAR
00511 NTAPI
00512 FstubDbgGuidToString(IN PGUID Guid,
00513 OUT PCHAR String)
00514 {
00515 sprintf(String,
00516 "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
00517 Guid->Data1,
00518 Guid->Data2,
00519 Guid->Data3,
00520 Guid->Data4[0],
00521 Guid->Data4[1],
00522 Guid->Data4[2],
00523 Guid->Data4[3],
00524 Guid->Data4[4],
00525 Guid->Data4[5],
00526 Guid->Data4[6],
00527 Guid->Data4[7]);
00528
00529 return String;
00530 }
00531
00532 VOID
00533 NTAPI
00534 FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
00535 {
00536 ULONG i;
00537 CHAR Guid[38];
00538 PAGED_CODE();
00539
00540 DPRINT("FSTUB: DRIVE_LAYOUT_INFORMATION_EX: %p\n", DriveLayout);
00541 switch (DriveLayout->PartitionStyle)
00542 {
00543 case PARTITION_STYLE_MBR:
00544 if (DriveLayout->PartitionCount % 4 != 0)
00545 {
00546 DPRINT("Warning: Partition count isn't a 4-factor: %ld!\n", DriveLayout->PartitionCount);
00547 }
00548
00549 DPRINT("Signature: %8.8x\n", DriveLayout->Mbr.Signature);
00550 for (i = 0; i < DriveLayout->PartitionCount; i++)
00551 {
00552 FstubDbgPrintPartitionEx(DriveLayout->PartitionEntry, i);
00553 }
00554
00555 break;
00556 case PARTITION_STYLE_GPT:
00557 FstubDbgGuidToString(&(DriveLayout->Gpt.DiskId), Guid);
00558 DPRINT("DiskId: %s\n", Guid);
00559 DPRINT("StartingUsableOffset: %I64x\n", DriveLayout->Gpt.StartingUsableOffset.QuadPart);
00560 DPRINT("UsableLength: %I64x\n", DriveLayout->Gpt.UsableLength.QuadPart);
00561 DPRINT("MaxPartitionCount: %ld\n", DriveLayout->Gpt.MaxPartitionCount);
00562 for (i = 0; i < DriveLayout->PartitionCount; i++)
00563 {
00564 FstubDbgPrintPartitionEx(DriveLayout->PartitionEntry, i);
00565 }
00566
00567 break;
00568 default:
00569 DPRINT("Unsupported partition style: %ld\n", DriveLayout->PartitionStyle);
00570 }
00571 }
00572
00573 VOID
00574 NTAPI
00575 FstubDbgPrintPartitionEx(IN PPARTITION_INFORMATION_EX PartitionEntry,
00576 IN ULONG PartitionNumber)
00577 {
00578 CHAR Guid[38];
00579 PAGED_CODE();
00580
00581 DPRINT("Printing partition %ld\n", PartitionNumber);
00582
00583 switch (PartitionEntry[PartitionNumber].PartitionStyle)
00584 {
00585 case PARTITION_STYLE_MBR:
00586 DPRINT(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
00587 DPRINT(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
00588 DPRINT(" RewritePartition: %d\n", PartitionEntry[PartitionNumber].RewritePartition);
00589 DPRINT(" PartitionType: %02x\n", PartitionEntry[PartitionNumber].Mbr.PartitionType);
00590 DPRINT(" BootIndicator: %d\n", PartitionEntry[PartitionNumber].Mbr.BootIndicator);
00591 DPRINT(" RecognizedPartition: %d\n", PartitionEntry[PartitionNumber].Mbr.RecognizedPartition);
00592 DPRINT(" HiddenSectors: %ld\n", PartitionEntry[PartitionNumber].Mbr.HiddenSectors);
00593
00594 break;
00595 case PARTITION_STYLE_GPT:
00596 DPRINT(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
00597 DPRINT(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
00598 DPRINT(" RewritePartition: %d\n", PartitionEntry[PartitionNumber].RewritePartition);
00599 FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionType), Guid);
00600 DPRINT(" PartitionType: %s\n", Guid);
00601 FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionId), Guid);
00602 DPRINT(" PartitionId: %s\n", Guid);
00603 DPRINT(" Attributes: %16x\n", PartitionEntry[PartitionNumber].Gpt.Attributes);
00604 DPRINT(" Name: %ws\n", PartitionEntry[PartitionNumber].Gpt.Name);
00605
00606 break;
00607 default:
00608 DPRINT(" Unsupported partition style: %ld\n", PartitionEntry[PartitionNumber].PartitionStyle);
00609 }
00610 }
00611
00612 VOID
00613 NTAPI
00614 FstubDbgPrintSetPartitionEx(IN PSET_PARTITION_INFORMATION_EX PartitionEntry,
00615 IN ULONG PartitionNumber)
00616 {
00617 CHAR Guid[38];
00618 PAGED_CODE();
00619
00620 DPRINT("FSTUB: SET_PARTITION_INFORMATION_EX: %p\n", PartitionEntry);
00621 DPRINT("Modifying partition %ld\n", PartitionNumber);
00622 switch (PartitionEntry->PartitionStyle)
00623 {
00624 case PARTITION_STYLE_MBR:
00625 DPRINT(" PartitionType: %02x\n", PartitionEntry->Mbr.PartitionType);
00626
00627 break;
00628 case PARTITION_STYLE_GPT:
00629 FstubDbgGuidToString(&(PartitionEntry->Gpt.PartitionType), Guid);
00630 DPRINT(" PartitionType: %s\n", Guid);
00631 FstubDbgGuidToString(&(PartitionEntry->Gpt.PartitionId), Guid);
00632 DPRINT(" PartitionId: %s\n", Guid);
00633 DPRINT(" Attributes: %16x\n", PartitionEntry->Gpt.Attributes);
00634 DPRINT(" Name: %ws\n", PartitionEntry->Gpt.Name);
00635
00636 break;
00637 default:
00638 DPRINT(" Unsupported partition style: %ld\n", PartitionEntry[PartitionNumber].PartitionStyle);
00639 }
00640 }
00641
00642 NTSTATUS
00643 NTAPI
00644 FstubDetectPartitionStyle(IN PDISK_INFORMATION Disk,
00645 IN PARTITION_STYLE * PartitionStyle)
00646 {
00647 NTSTATUS Status;
00648 PPARTITION_DESCRIPTOR PartitionDescriptor;
00649 PAGED_CODE();
00650
00651 ASSERT(IS_VALID_DISK_INFO(Disk));
00652 ASSERT(PartitionStyle);
00653
00654
00655 Status = FstubReadSector(Disk->DeviceObject,
00656 Disk->SectorSize,
00657 0,
00658 Disk->Buffer);
00659 if (!NT_SUCCESS(Status))
00660 {
00661 return Status;
00662 }
00663
00664
00665 PartitionDescriptor = (PPARTITION_DESCRIPTOR)
00666 &(Disk->Buffer[PARTITION_TABLE_OFFSET]);
00667
00668 if (Disk->Buffer[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE)
00669 {
00670 *PartitionStyle = PARTITION_STYLE_RAW;
00671 }
00672
00673 else if (PartitionDescriptor[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
00674 PartitionDescriptor[1].PartitionType == 0 &&
00675 PartitionDescriptor[2].PartitionType == 0 &&
00676 PartitionDescriptor[3].PartitionType == 0)
00677 {
00678 *PartitionStyle = PARTITION_STYLE_GPT;
00679 }
00680
00681 else
00682 {
00683 *PartitionStyle = PARTITION_STYLE_MBR;
00684 }
00685
00686 return STATUS_SUCCESS;
00687 }
00688
00689 VOID
00690 NTAPI
00691 FstubFreeDiskInformation(IN PDISK_INFORMATION DiskBuffer)
00692 {
00693 if (DiskBuffer)
00694 {
00695 if (DiskBuffer->Buffer)
00696 {
00697 ExFreePoolWithTag(DiskBuffer->Buffer, TAG_FSTUB);
00698 }
00699 ExFreePoolWithTag(DiskBuffer, TAG_FSTUB);
00700 }
00701 }
00702
00703 NTSTATUS
00704 NTAPI
00705 FstubGetDiskGeometry(IN PDEVICE_OBJECT DeviceObject,
00706 OUT PDISK_GEOMETRY_EX Geometry)
00707 {
00708 PIRP Irp;
00709 NTSTATUS Status;
00710 PKEVENT Event = NULL;
00711 PDISK_GEOMETRY_EX DiskGeometry = NULL;
00712 PIO_STATUS_BLOCK IoStatusBlock = NULL;
00713 PAGED_CODE();
00714
00715 ASSERT(DeviceObject);
00716 ASSERT(Geometry);
00717
00718
00719 DiskGeometry = ExAllocatePoolWithTag(NonPagedPool, sizeof(DISK_GEOMETRY_EX), TAG_FSTUB);
00720 if (!DiskGeometry)
00721 {
00722 Status = STATUS_INSUFFICIENT_RESOURCES;
00723 goto Cleanup;
00724 }
00725
00726 IoStatusBlock = ExAllocatePoolWithTag(NonPagedPool, sizeof(IO_STATUS_BLOCK), TAG_FSTUB);
00727 if (!IoStatusBlock)
00728 {
00729 Status = STATUS_INSUFFICIENT_RESOURCES;
00730 goto Cleanup;
00731 }
00732
00733 Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_FSTUB);
00734 if (!Event)
00735 {
00736 Status = STATUS_INSUFFICIENT_RESOURCES;
00737 goto Cleanup;
00738 }
00739
00740 KeInitializeEvent(Event, NotificationEvent, FALSE);
00741
00742
00743 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
00744 DeviceObject,
00745 0,
00746 0,
00747 DiskGeometry,
00748 sizeof(DISK_GEOMETRY_EX),
00749 FALSE,
00750 Event,
00751 IoStatusBlock);
00752 if (!Irp)
00753 {
00754 Status = STATUS_INSUFFICIENT_RESOURCES;
00755 goto Cleanup;
00756 }
00757
00758
00759 Status = IoCallDriver(DeviceObject, Irp);
00760 if (Status == STATUS_PENDING)
00761 {
00762 KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
00763 Status = IoStatusBlock->Status;
00764 }
00765
00766
00767 if (NT_SUCCESS(Status))
00768 {
00769 *Geometry = *DiskGeometry;
00770 }
00771
00772 Cleanup:
00773 if (DiskGeometry)
00774 {
00775 ExFreePoolWithTag(DiskGeometry, TAG_FSTUB);
00776
00777 if (NT_SUCCESS(Status))
00778 {
00779 ASSERT(Geometry->Geometry.BytesPerSector % PARTITION_ENTRY_SIZE == 0);
00780 }
00781 }
00782
00783 if (IoStatusBlock)
00784 {
00785 ExFreePoolWithTag(IoStatusBlock, TAG_FSTUB);
00786 }
00787
00788 if (Event)
00789 {
00790 ExFreePoolWithTag(Event, TAG_FSTUB);
00791 }
00792
00793 return Status;
00794 }
00795
00796 NTSTATUS
00797 NTAPI
00798 FstubReadHeaderEFI(IN PDISK_INFORMATION Disk,
00799 IN BOOLEAN ReadBackupTable,
00800 PEFI_PARTITION_HEADER HeaderBuffer)
00801 {
00802 NTSTATUS Status;
00803 PUCHAR Sector = NULL;
00804 ULONGLONG StartingSector;
00805 PEFI_PARTITION_HEADER EFIHeader;
00806 ULONG i, HeaderCRC32, PreviousCRC32, SectoredPartitionEntriesSize, LonelyPartitions;
00807 PAGED_CODE();
00808
00809 ASSERT(Disk);
00810 ASSERT(IS_VALID_DISK_INFO(Disk));
00811 ASSERT(HeaderBuffer);
00812
00813
00814 if (ReadBackupTable)
00815 {
00816 StartingSector = Disk->SectorCount - 1ULL;
00817 }
00818 else
00819 {
00820
00821 StartingSector = 1ULL;
00822 }
00823
00824 Status = FstubReadSector(Disk->DeviceObject,
00825 Disk->SectorSize,
00826 StartingSector,
00827 Disk->Buffer);
00828 if (!NT_SUCCESS(Status))
00829 {
00830 DPRINT("EFI::Failed reading header!\n");
00831 return Status;
00832 }
00833
00834 EFIHeader = (PEFI_PARTITION_HEADER)Disk->Buffer;
00835
00836
00837
00838
00839
00840
00841 if (EFIHeader->Signature != EFI_HEADER_SIGNATURE ||
00842 EFIHeader->Revision != EFI_HEADER_REVISION_1 ||
00843 EFIHeader->HeaderSize != sizeof(EFI_PARTITION_HEADER))
00844 {
00845 DPRINT("EFI::Wrong signature/version/header size!\n");
00846 DPRINT("%I64x (expected: %I64x)\n", EFIHeader->Signature, EFI_HEADER_SIGNATURE);
00847 DPRINT("%03x (expected: %03x)\n", EFIHeader->Revision, EFI_HEADER_REVISION_1);
00848 DPRINT("%02x (expected: %02x)\n", EFIHeader->HeaderSize, sizeof(EFI_PARTITION_HEADER));
00849 return STATUS_DISK_CORRUPT_ERROR;
00850 }
00851
00852
00853 HeaderCRC32 = EFIHeader->HeaderCRC32;
00854
00855 EFIHeader->HeaderCRC32 = 0;
00856
00857 if (RtlComputeCrc32(0, (PUCHAR)Disk->Buffer, sizeof(EFI_PARTITION_HEADER)) != HeaderCRC32)
00858 {
00859 DPRINT("EFI::Not matching header checksum!\n");
00860 return STATUS_DISK_CORRUPT_ERROR;
00861 }
00862
00863 EFIHeader->HeaderCRC32 = HeaderCRC32;
00864
00865
00866 if (EFIHeader->MyLBA != StartingSector)
00867 {
00868 DPRINT("EFI::Not matching starting sector!\n");
00869 return STATUS_DISK_CORRUPT_ERROR;
00870 }
00871
00872
00873 Sector = ExAllocatePoolWithTag(NonPagedPool,
00874 Disk->SectorSize,
00875 TAG_FSTUB);
00876 if (!Sector)
00877 {
00878 DPRINT("EFI::Lacking resources!\n");
00879 return STATUS_INSUFFICIENT_RESOURCES;
00880 }
00881
00882
00883 SectoredPartitionEntriesSize = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
00884
00885 for (i = 0, PreviousCRC32 = 0; i < SectoredPartitionEntriesSize; i++)
00886 {
00887 Status = FstubReadSector(Disk->DeviceObject,
00888 Disk->SectorSize,
00889 EFIHeader->PartitionEntryLBA + i,
00890 (PUSHORT)Sector);
00891 if (!NT_SUCCESS(Status))
00892 {
00893 ExFreePoolWithTag(Sector, TAG_FSTUB);
00894 DPRINT("EFI::Failed reading sector for partition entry!\n");
00895 return Status;
00896 }
00897
00898 PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector, Disk->SectorSize);
00899 }
00900
00901
00902 LonelyPartitions = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) % Disk->SectorSize;
00903
00904 if (LonelyPartitions != 0)
00905 {
00906
00907 Status = FstubReadSector(Disk->DeviceObject,
00908 Disk->SectorSize,
00909 EFIHeader->PartitionEntryLBA + i,
00910 (PUSHORT)Sector);
00911 if (!NT_SUCCESS(Status))
00912 {
00913 ExFreePoolWithTag(Sector, TAG_FSTUB);
00914 DPRINT("EFI::Failed reading sector for partition entry!\n");
00915 return Status;
00916 }
00917
00918
00919 for (i = 0; i < LonelyPartitions; i++)
00920 {
00921 PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector + i * PARTITION_ENTRY_SIZE, PARTITION_ENTRY_SIZE);
00922 }
00923 }
00924
00925
00926 ExFreePoolWithTag(Sector, TAG_FSTUB);
00927
00928
00929 if (PreviousCRC32 == EFIHeader->PartitionEntryCRC32)
00930 {
00931
00932 *HeaderBuffer = *EFIHeader;
00933 return STATUS_SUCCESS;
00934 }
00935 else
00936 {
00937 DPRINT("EFI::Not matching partition table checksum!\n");
00938 DPRINT("EFI::Expected: %x, received: %x\n", EFIHeader->PartitionEntryCRC32, PreviousCRC32);
00939 return STATUS_DISK_CORRUPT_ERROR;
00940 }
00941 }
00942
00943 NTSTATUS
00944 NTAPI
00945 FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk,
00946 IN BOOLEAN ReadBackupTable,
00947 OUT struct _DRIVE_LAYOUT_INFORMATION_EX** DriveLayout)
00948 {
00949 NTSTATUS Status;
00950 EFI_PARTITION_HEADER EfiHeader;
00951 ULONGLONG SectorsForPartitions;
00952 EFI_PARTITION_ENTRY PartitionEntry;
00953 BOOLEAN UpdatedPartitionTable = FALSE;
00954 PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
00955 ULONG i, PartitionCount, PartitionIndex, PartitionsPerSector;
00956 PAGED_CODE();
00957
00958 ASSERT(Disk);
00959
00960
00961 *DriveLayout = NULL;
00962
00963
00964 Status = FstubReadHeaderEFI(Disk,
00965 ReadBackupTable,
00966 &EfiHeader);
00967 if (!NT_SUCCESS(Status))
00968 {
00969 return Status;
00970 }
00971
00972
00973 DriveLayoutEx = ExAllocatePoolWithTag(NonPagedPool,
00974 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) +
00975 EfiHeader.NumberOfEntries * sizeof(PARTITION_INFORMATION_EX),
00976 TAG_FSTUB);
00977 if (!DriveLayoutEx)
00978 {
00979 return STATUS_INSUFFICIENT_RESOURCES;
00980 }
00981
00982 if (ReadBackupTable)
00983 {
00984
00985 if ((Disk->SectorCount - 1ULL) != EfiHeader.AlternateLBA)
00986 {
00987
00988 SectorsForPartitions = ((ULONGLONG)EfiHeader.NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
00989
00990 EfiHeader.FirstUsableLBA = SectorsForPartitions + 2;
00991
00992 EfiHeader.LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
00993
00994 UpdatedPartitionTable = TRUE;
00995 }
00996 }
00997
00998 DriveLayoutEx->PartitionStyle = PARTITION_STYLE_GPT;
00999
01000 DriveLayoutEx->Gpt.StartingUsableOffset.QuadPart = EfiHeader.FirstUsableLBA * Disk->SectorSize;
01001 DriveLayoutEx->Gpt.UsableLength.QuadPart = EfiHeader.LastUsableLBA - EfiHeader.FirstUsableLBA * Disk->SectorSize;
01002 DriveLayoutEx->Gpt.MaxPartitionCount = EfiHeader.NumberOfEntries;
01003 DriveLayoutEx->Gpt.DiskId = EfiHeader.DiskGUID;
01004
01005
01006 PartitionsPerSector = (Disk->SectorSize / PARTITION_ENTRY_SIZE);
01007
01008 for (i = 0, PartitionCount = 0, PartitionIndex = PartitionsPerSector;
01009 i < EfiHeader.NumberOfEntries;
01010 i++)
01011 {
01012
01013 if (PartitionIndex == PartitionsPerSector)
01014 {
01015 Status = FstubReadSector(Disk->DeviceObject,
01016 Disk->SectorSize,
01017 EfiHeader.PartitionEntryLBA + (i / PartitionsPerSector),
01018 Disk->Buffer);
01019 if (!NT_SUCCESS(Status))
01020 {
01021 ExFreePoolWithTag(DriveLayoutEx, TAG_FSTUB);
01022 return Status;
01023 }
01024
01025 PartitionIndex = 0;
01026 }
01027
01028 PartitionEntry = ((PEFI_PARTITION_ENTRY)Disk->Buffer)[PartitionIndex];
01029 PartitionIndex++;
01030
01031
01032 if (PartitionEntry.PartitionType.Data1 == 0 &&
01033 PartitionEntry.PartitionType.Data2 == 0 &&
01034 PartitionEntry.PartitionType.Data3 == 0 &&
01035 ((PULONGLONG)PartitionEntry.PartitionType.Data4)[0] == 0)
01036 {
01037 continue;
01038 }
01039
01040
01041 DriveLayoutEx->PartitionEntry[PartitionCount].StartingOffset.QuadPart = PartitionEntry.StartingLBA * Disk->SectorSize;
01042 DriveLayoutEx->PartitionEntry[PartitionCount].PartitionLength.QuadPart = (PartitionEntry.EndingLBA -
01043 PartitionEntry.StartingLBA + 1) *
01044 Disk->SectorSize;
01045
01046 DriveLayoutEx->PartitionEntry[PartitionCount].PartitionNumber = PartitionCount + 1;
01047 DriveLayoutEx->PartitionEntry[PartitionCount].RewritePartition = FALSE;
01048 DriveLayoutEx->PartitionEntry[PartitionCount].PartitionStyle = PARTITION_STYLE_GPT;
01049 DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.PartitionType = PartitionEntry.PartitionType;
01050 DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.PartitionId = PartitionEntry.UniquePartition;
01051 DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.Attributes = PartitionEntry.Attributes;
01052 RtlCopyMemory(DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.Name,
01053 PartitionEntry.Name, sizeof(PartitionEntry.Name));
01054
01055
01056 PartitionCount++;
01057 }
01058 DriveLayoutEx->PartitionCount = PartitionCount;
01059
01060
01061 if (UpdatedPartitionTable)
01062 {
01063 IoWritePartitionTableEx(Disk->DeviceObject,
01064 DriveLayoutEx);
01065 }
01066
01067
01068 *DriveLayout = DriveLayoutEx;
01069
01070 return Status;
01071 }
01072
01073 NTSTATUS
01074 NTAPI
01075 FstubReadPartitionTableMBR(IN PDISK_INFORMATION Disk,
01076 IN BOOLEAN ReturnRecognizedPartitions,
01077 OUT struct _DRIVE_LAYOUT_INFORMATION_EX** ReturnedDriveLayout)
01078 {
01079 ULONG i;
01080 NTSTATUS Status;
01081 PDRIVE_LAYOUT_INFORMATION DriveLayout = NULL;
01082 PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
01083 PAGED_CODE();
01084
01085 ASSERT(IS_VALID_DISK_INFO(Disk));
01086 ASSERT(ReturnedDriveLayout);
01087
01088
01089 *ReturnedDriveLayout = NULL;
01090
01091
01092 Status = IoReadPartitionTable(Disk->DeviceObject,
01093 Disk->SectorSize,
01094 ReturnRecognizedPartitions,
01095 &DriveLayout);
01096 if (!NT_SUCCESS(Status))
01097 {
01098 return Status;
01099 }
01100
01101
01102 DriveLayoutEx = ExAllocatePoolWithTag(NonPagedPool,
01103 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) +
01104 DriveLayout->PartitionCount * sizeof(PARTITION_INFORMATION_EX),
01105 TAG_FSTUB);
01106 if (!DriveLayoutEx)
01107 {
01108
01109 ExFreePool(DriveLayout);
01110 return STATUS_INSUFFICIENT_RESOURCES;
01111 }
01112
01113
01114 DriveLayoutEx->PartitionStyle = PARTITION_STYLE_MBR;
01115 DriveLayoutEx->PartitionCount = DriveLayout->PartitionCount;
01116 DriveLayoutEx->Mbr.Signature = DriveLayout->Signature;
01117
01118
01119 for (i = 0; i < DriveLayout->PartitionCount; i++)
01120 {
01121 DriveLayoutEx->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
01122 DriveLayoutEx->PartitionEntry[i].StartingOffset = DriveLayout->PartitionEntry[i].StartingOffset;
01123 DriveLayoutEx->PartitionEntry[i].PartitionLength = DriveLayout->PartitionEntry[i].PartitionLength;
01124 DriveLayoutEx->PartitionEntry[i].PartitionNumber = DriveLayout->PartitionEntry[i].PartitionNumber;
01125 DriveLayoutEx->PartitionEntry[i].RewritePartition = DriveLayout->PartitionEntry[i].RewritePartition;
01126 DriveLayoutEx->PartitionEntry[i].Mbr.PartitionType = DriveLayout->PartitionEntry[i].PartitionType;
01127 DriveLayoutEx->PartitionEntry[i].Mbr.BootIndicator = DriveLayout->PartitionEntry[i].BootIndicator;
01128 DriveLayoutEx->PartitionEntry[i].Mbr.RecognizedPartition = DriveLayout->PartitionEntry[i].RecognizedPartition;
01129 DriveLayoutEx->PartitionEntry[i].Mbr.HiddenSectors = DriveLayout->PartitionEntry[i].HiddenSectors;
01130 }
01131
01132
01133 *ReturnedDriveLayout = DriveLayoutEx;
01134 ExFreePool(DriveLayout);
01135
01136 return STATUS_SUCCESS;
01137 }
01138
01139 NTSTATUS
01140 NTAPI
01141 FstubReadSector(IN PDEVICE_OBJECT DeviceObject,
01142 IN ULONG SectorSize,
01143 IN ULONGLONG StartingSector OPTIONAL,
01144 OUT PUSHORT Buffer)
01145 {
01146 PIRP Irp;
01147 KEVENT Event;
01148 NTSTATUS Status;
01149 LARGE_INTEGER StartingOffset;
01150 IO_STATUS_BLOCK IoStatusBlock;
01151 PIO_STACK_LOCATION IoStackLocation;
01152 PAGED_CODE();
01153
01154 ASSERT(DeviceObject);
01155 ASSERT(Buffer);
01156 ASSERT(SectorSize);
01157
01158
01159 StartingOffset.QuadPart = StartingSector * SectorSize;
01160
01161
01162 KeInitializeEvent(&Event, NotificationEvent, FALSE);
01163
01164
01165 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
01166 DeviceObject,
01167 Buffer,
01168 SectorSize,
01169 &StartingOffset,
01170 &Event,
01171 &IoStatusBlock);
01172 if (!Irp)
01173 {
01174 return STATUS_INSUFFICIENT_RESOURCES;
01175 }
01176
01177
01178 IoStackLocation = IoGetNextIrpStackLocation(Irp);
01179 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
01180
01181
01182 Status = IoCallDriver(DeviceObject, Irp);
01183 if (Status == STATUS_PENDING)
01184 {
01185 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
01186 Status = IoStatusBlock.Status;
01187 }
01188
01189 return Status;
01190 }
01191
01192 NTSTATUS
01193 NTAPI
01194 FstubSetPartitionInformationEFI(IN PDISK_INFORMATION Disk,
01195 IN ULONG PartitionNumber,
01196 IN SET_PARTITION_INFORMATION_GPT * PartitionInfo)
01197 {
01198 NTSTATUS Status;
01199 PDRIVE_LAYOUT_INFORMATION_EX Layout = NULL;
01200 PAGED_CODE();
01201
01202 ASSERT(Disk);
01203 ASSERT(PartitionInfo);
01204
01205
01206 if (PartitionNumber == 0)
01207 {
01208 return STATUS_INVALID_PARAMETER;
01209 }
01210
01211
01212 Status = IoReadPartitionTableEx(Disk->DeviceObject, &Layout);
01213 if (!NT_SUCCESS(Status))
01214 {
01215 return Status;
01216 }
01217 ASSERT(Layout);
01218
01219
01220 if (Layout->PartitionCount <= --PartitionNumber)
01221 {
01222 ExFreePool(Layout);
01223 return STATUS_INVALID_PARAMETER;
01224 }
01225
01226
01227 Layout->PartitionEntry[PartitionNumber].Gpt.PartitionType = PartitionInfo->PartitionType;
01228 Layout->PartitionEntry[PartitionNumber].Gpt.PartitionId = PartitionInfo->PartitionId;
01229 Layout->PartitionEntry[PartitionNumber].Gpt.Attributes = PartitionInfo->Attributes;
01230 RtlCopyMemory(Layout->PartitionEntry[PartitionNumber].Gpt.Name, PartitionInfo->Name, sizeof(PartitionInfo->Name));
01231
01232
01233 Status = IoWritePartitionTableEx(Disk->DeviceObject, Layout);
01234
01235
01236 ExFreePool(Layout);
01237 return Status;
01238 }
01239
01240 NTSTATUS
01241 NTAPI
01242 FstubVerifyPartitionTableEFI(IN PDISK_INFORMATION Disk,
01243 IN BOOLEAN FixErrors)
01244 {
01245 NTSTATUS Status;
01246 PEFI_PARTITION_HEADER EFIHeader;
01247 EFI_PARTITION_HEADER ReadEFIHeader;
01248 BOOLEAN PrimaryValid = FALSE, BackupValid = FALSE;
01249 PAGED_CODE();
01250
01251 EFIHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(EFI_PARTITION_HEADER), TAG_FSTUB);
01252 if (!EFIHeader)
01253 {
01254 return STATUS_INSUFFICIENT_RESOURCES;
01255 }
01256
01257 Status = FstubReadHeaderEFI(Disk, FALSE, &ReadEFIHeader);
01258 if (NT_SUCCESS(Status))
01259 {
01260 PrimaryValid = TRUE;
01261 }
01262
01263 Status = FstubReadHeaderEFI(Disk, TRUE, &ReadEFIHeader);
01264 if (NT_SUCCESS(Status))
01265 {
01266 BackupValid = TRUE;
01267 }
01268
01269 if (!PrimaryValid)
01270 {
01271 if (!BackupValid || !FixErrors)
01272 {
01273 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
01274 return STATUS_DISK_CORRUPT_ERROR;
01275 }
01276
01277 DPRINT1("EFI::Partition table fixing not yet supported!\n");
01278 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
01279 return STATUS_NOT_IMPLEMENTED;
01280 }
01281 else if (!BackupValid)
01282 {
01283 if (!PrimaryValid || !FixErrors)
01284 {
01285 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
01286 return STATUS_DISK_CORRUPT_ERROR;
01287 }
01288
01289 DPRINT1("EFI::Partition table fixing not yet supported!\n");
01290 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
01291 return STATUS_NOT_IMPLEMENTED;
01292 }
01293 else
01294 {
01295 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
01296 return STATUS_SUCCESS;
01297 }
01298 }
01299
01300 NTSTATUS
01301 NTAPI
01302 FstubWriteBootSectorEFI(IN PDISK_INFORMATION Disk)
01303 {
01304 NTSTATUS Status;
01305 ULONG Signature = 0;
01306 PMASTER_BOOT_RECORD MasterBootRecord;
01307 PAGED_CODE();
01308
01309 ASSERT(Disk);
01310 ASSERT(IS_VALID_DISK_INFO(Disk));
01311
01312
01313 Status = FstubReadSector(Disk->DeviceObject,
01314 Disk->SectorSize,
01315 0ULL,
01316 Disk->Buffer);
01317 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
01318
01319 if (NT_SUCCESS(Status) && MasterBootRecord->MasterBootRecordMagic == BOOT_RECORD_SIGNATURE)
01320 {
01321
01322 Signature = MasterBootRecord->Signature;
01323 }
01324
01325
01326 RtlZeroMemory(MasterBootRecord, Disk->SectorSize);
01327
01328
01329
01330
01331
01332
01333
01334 MasterBootRecord->Signature = Signature;
01335 MasterBootRecord->PartitionTable[0].StartSector = 2;
01336 MasterBootRecord->PartitionTable[0].SystemIndicator = EFI_PMBR_OSTYPE_EFI;
01337 MasterBootRecord->PartitionTable[0].EndHead = 0xFF;
01338 MasterBootRecord->PartitionTable[0].EndSector = 0xFF;
01339 MasterBootRecord->PartitionTable[0].EndCylinder = 0xFF;
01340 MasterBootRecord->PartitionTable[0].SectorCountBeforePartition = 1;
01341 MasterBootRecord->PartitionTable[0].PartitionSectorCount = 0xFFFFFFFF;
01342 MasterBootRecord->MasterBootRecordMagic = BOOT_RECORD_SIGNATURE;
01343
01344
01345 return FstubWriteSector(Disk->DeviceObject,
01346 Disk->SectorSize,
01347 0,
01348 Disk->Buffer);
01349 }
01350
01351 NTSTATUS
01352 NTAPI
01353 FstubWriteEntryEFI(IN PDISK_INFORMATION Disk,
01354 IN ULONG PartitionsSizeSector,
01355 IN ULONG PartitionEntryNumber,
01356 IN PEFI_PARTITION_ENTRY PartitionEntry,
01357 IN BOOLEAN WriteBackupTable,
01358 IN BOOLEAN ForceWrite,
01359 OUT PULONG PartitionEntryCRC32 OPTIONAL)
01360 {
01361 ULONG Offset;
01362 ULONGLONG FirstEntryLBA;
01363 NTSTATUS Status = STATUS_SUCCESS;
01364 PAGED_CODE();
01365
01366 ASSERT(Disk);
01367 ASSERT(IS_VALID_DISK_INFO(Disk));
01368
01369
01370
01371
01372
01373 if (!WriteBackupTable)
01374 {
01375 FirstEntryLBA = 2ULL;
01376 }
01377 else
01378 {
01379 FirstEntryLBA = Disk->SectorCount - PartitionsSizeSector - 1;
01380 }
01381
01382
01383
01384
01385 RtlCopyMemory(Disk->Buffer + (((PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize) / sizeof(PUSHORT)),
01386 PartitionEntry,
01387 sizeof(EFI_PARTITION_ENTRY));
01388
01389 Offset = (PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize + PARTITION_ENTRY_SIZE;
01390 ASSERT(Offset <= Disk->SectorSize);
01391
01392
01393 if (Offset == Disk->SectorSize || ForceWrite)
01394 {
01395
01396 Status = FstubWriteSector(Disk->DeviceObject,
01397 Disk->SectorSize,
01398 FirstEntryLBA + ((PartitionEntryNumber * PARTITION_ENTRY_SIZE) / Disk->SectorSize),
01399 Disk->Buffer);
01400 if (!NT_SUCCESS(Status))
01401 {
01402 return Status;
01403 }
01404
01405 RtlZeroMemory(Disk->Buffer, Disk->SectorSize);
01406 }
01407
01408
01409 if (PartitionEntryCRC32)
01410 {
01411 *PartitionEntryCRC32 = RtlComputeCrc32(*PartitionEntryCRC32, (PUCHAR)PartitionEntry, PARTITION_ENTRY_SIZE);
01412 }
01413
01414 return Status;
01415 }
01416
01417 NTSTATUS
01418 NTAPI
01419 FstubWriteHeaderEFI(IN PDISK_INFORMATION Disk,
01420 IN ULONG PartitionsSizeSector,
01421 IN GUID DiskGUID,
01422 IN ULONG NumberOfEntries,
01423 IN ULONGLONG FirstUsableLBA,
01424 IN ULONGLONG LastUsableLBA,
01425 IN ULONG PartitionEntryCRC32,
01426 IN BOOLEAN WriteBackupTable)
01427 {
01428 PEFI_PARTITION_HEADER EFIHeader;
01429 PAGED_CODE();
01430
01431 ASSERT(Disk);
01432 ASSERT(IS_VALID_DISK_INFO(Disk));
01433
01434
01435 EFIHeader = (PEFI_PARTITION_HEADER)Disk->Buffer;
01436
01437
01438 EFIHeader->Signature = EFI_HEADER_SIGNATURE;
01439 EFIHeader->Revision = EFI_HEADER_REVISION_1;
01440 EFIHeader->HeaderSize = sizeof(EFI_PARTITION_HEADER);
01441
01442 EFIHeader->HeaderCRC32 = 0;
01443 EFIHeader->Reserved = 0;
01444
01445
01446
01447
01448
01449 if (!WriteBackupTable)
01450 {
01451 EFIHeader->MyLBA = 1ULL;
01452 EFIHeader->AlternateLBA = Disk->SectorCount - 1ULL;
01453 }
01454 else
01455 {
01456 EFIHeader->MyLBA = Disk->SectorCount - 1ULL;
01457 EFIHeader->AlternateLBA = 1ULL;
01458 }
01459
01460 EFIHeader->FirstUsableLBA = FirstUsableLBA;
01461 EFIHeader->LastUsableLBA = LastUsableLBA;
01462 EFIHeader->DiskGUID = DiskGUID;
01463
01464
01465
01466
01467
01468 if (!WriteBackupTable)
01469 {
01470 EFIHeader->PartitionEntryLBA = EFIHeader->MyLBA + 1ULL;
01471 }
01472 else
01473 {
01474 EFIHeader->PartitionEntryLBA = EFIHeader->MyLBA - PartitionsSizeSector;
01475 }
01476
01477 EFIHeader->NumberOfEntries = NumberOfEntries;
01478 EFIHeader->SizeOfPartitionEntry = PARTITION_ENTRY_SIZE;
01479 EFIHeader->PartitionEntryCRC32 = PartitionEntryCRC32;
01480
01481 EFIHeader->HeaderCRC32 = RtlComputeCrc32(0, (PUCHAR)EFIHeader, sizeof(EFI_PARTITION_HEADER));
01482
01483
01484 DPRINT("FSTUB: About to write the following header for %s table\n", (WriteBackupTable ? "backup" : "primary"));
01485 DPRINT(" Signature: %I64x\n Revision: %x\n HeaderSize: %x\n HeaderCRC32: %x\n",
01486 EFIHeader->Signature, EFIHeader->Revision, EFIHeader->HeaderSize, EFIHeader->HeaderCRC32);
01487 DPRINT(" MyLBA: %I64x\n AlternateLBA: %I64x\n FirstUsableLBA: %I64x\n LastUsableLBA: %I64x\n",
01488 EFIHeader->MyLBA, EFIHeader->AlternateLBA, EFIHeader->FirstUsableLBA, EFIHeader->LastUsableLBA);
01489 DPRINT(" PartitionEntryLBA: %I64x\n NumberOfEntries: %x\n SizeOfPartitionEntry: %x\n PartitionEntryCRC32: %x\n",
01490 EFIHeader->PartitionEntryLBA, EFIHeader->NumberOfEntries,
01491 EFIHeader->SizeOfPartitionEntry, EFIHeader->PartitionEntryCRC32);
01492
01493
01494 return FstubWriteSector(Disk->DeviceObject,
01495 Disk->SectorSize,
01496 EFIHeader->MyLBA,
01497 Disk->Buffer);
01498 }
01499
01500 NTSTATUS
01501 NTAPI
01502 FstubWritePartitionTableEFI(IN PDISK_INFORMATION Disk,
01503 IN GUID DiskGUID,
01504 IN ULONG MaxPartitionCount,
01505 IN ULONGLONG FirstUsableLBA,
01506 IN ULONGLONG LastUsableLBA,
01507 IN BOOLEAN WriteBackupTable,
01508 IN ULONG PartitionCount,
01509 IN PPARTITION_INFORMATION_EX PartitionEntries OPTIONAL)
01510 {
01511 NTSTATUS Status;
01512 EFI_PARTITION_ENTRY Entry;
01513 ULONG i, WrittenPartitions, SectoredPartitionEntriesSize, PartitionEntryCRC32;
01514 PAGED_CODE();
01515
01516 ASSERT(Disk);
01517 ASSERT(MaxPartitionCount >= 128);
01518 ASSERT(PartitionCount <= MaxPartitionCount);
01519
01520 PartitionEntryCRC32 = 0;
01521
01522 SectoredPartitionEntriesSize = (MaxPartitionCount * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
01523
01524 for (i = 0, WrittenPartitions = 0; i < PartitionCount; i++)
01525 {
01526
01527 if (PartitionEntries[i].Gpt.PartitionType.Data1 == 0 &&
01528 PartitionEntries[i].Gpt.PartitionType.Data2 == 0 &&
01529 PartitionEntries[i].Gpt.PartitionType.Data3 == 0 &&
01530 ((PULONGLONG)PartitionEntries[i].Gpt.PartitionType.Data4)[0] == 0)
01531 {
01532 continue;
01533 }
01534
01535
01536 FstubCopyEntryEFI(&Entry, &PartitionEntries[i], Disk->SectorSize);
01537
01538 Status = FstubWriteEntryEFI(Disk,
01539 SectoredPartitionEntriesSize,
01540 WrittenPartitions,
01541 &Entry,
01542 WriteBackupTable,
01543 FALSE,
01544 &PartitionEntryCRC32);
01545 if (!NT_SUCCESS(Status))
01546 {
01547 return Status;
01548 }
01549 WrittenPartitions++;
01550 }
01551
01552
01553 RtlZeroMemory(&Entry, sizeof(EFI_PARTITION_ENTRY));
01554
01555 for (i = WrittenPartitions; i < MaxPartitionCount; i++)
01556 {
01557 Status = FstubWriteEntryEFI(Disk,
01558 SectoredPartitionEntriesSize,
01559 i,
01560 &Entry,
01561 WriteBackupTable,
01562 FALSE,
01563 &PartitionEntryCRC32);
01564 if (!NT_SUCCESS(Status))
01565 {
01566 return Status;
01567 }
01568 }
01569
01570
01571 return FstubWriteHeaderEFI(Disk,
01572 SectoredPartitionEntriesSize,
01573 DiskGUID,
01574 MaxPartitionCount,
01575 FirstUsableLBA,
01576 LastUsableLBA,
01577 PartitionEntryCRC32,
01578 WriteBackupTable);
01579 }
01580
01581 NTSTATUS
01582 NTAPI
01583 FstubWritePartitionTableMBR(IN PDISK_INFORMATION Disk,
01584 IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
01585 {
01586 NTSTATUS Status;
01587 PDRIVE_LAYOUT_INFORMATION DriveLayout;
01588 PAGED_CODE();
01589
01590 ASSERT(IS_VALID_DISK_INFO(Disk));
01591 ASSERT(LayoutEx);
01592
01593
01594 DriveLayout = FstubConvertExtendedToLayout(LayoutEx);
01595 if (!DriveLayout)
01596 {
01597 return STATUS_INSUFFICIENT_RESOURCES;
01598 }
01599
01600
01601 Status = IoWritePartitionTable(Disk->DeviceObject,
01602 Disk->SectorSize,
01603 Disk->DiskGeometry.Geometry.SectorsPerTrack,
01604 Disk->DiskGeometry.Geometry.TracksPerCylinder,
01605 DriveLayout);
01606
01607
01608 ExFreePoolWithTag(DriveLayout, TAG_FSTUB);
01609 return Status;
01610 }
01611
01612 NTSTATUS
01613 NTAPI
01614 FstubWriteSector(IN PDEVICE_OBJECT DeviceObject,
01615 IN ULONG SectorSize,
01616 IN ULONGLONG StartingSector OPTIONAL,
01617 IN PUSHORT Buffer)
01618 {
01619 PIRP Irp;
01620 KEVENT Event;
01621 NTSTATUS Status;
01622 LARGE_INTEGER StartingOffset;
01623 IO_STATUS_BLOCK IoStatusBlock;
01624 PIO_STACK_LOCATION IoStackLocation;
01625 PAGED_CODE();
01626
01627 ASSERT(DeviceObject);
01628 ASSERT(Buffer);
01629 ASSERT(SectorSize);
01630
01631
01632 StartingOffset.QuadPart = StartingSector * SectorSize;
01633
01634
01635 KeInitializeEvent(&Event, NotificationEvent, FALSE);
01636
01637
01638 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
01639 DeviceObject,
01640 Buffer,
01641 SectorSize,
01642 &StartingOffset,
01643 &Event,
01644 &IoStatusBlock);
01645 if (!Irp)
01646 {
01647 return STATUS_INSUFFICIENT_RESOURCES;
01648 }
01649
01650
01651 IoStackLocation = IoGetNextIrpStackLocation(Irp);
01652 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
01653
01654
01655 Status = IoCallDriver(DeviceObject, Irp);
01656 if (Status == STATUS_PENDING)
01657 {
01658 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
01659 Status = IoStatusBlock.Status;
01660 }
01661
01662 return Status;
01663 }
01664
01665
01666
01667
01668
01669
01670 NTSTATUS
01671 NTAPI
01672 IoCreateDisk(IN PDEVICE_OBJECT DeviceObject,
01673 IN struct _CREATE_DISK* Disk)
01674 {
01675 PARTITION_STYLE PartitionStyle;
01676 PAGED_CODE();
01677
01678 ASSERT(DeviceObject);
01679
01680
01681 PartitionStyle = ((Disk) ? Disk->PartitionStyle : PARTITION_STYLE_RAW);
01682
01683 switch (PartitionStyle)
01684 {
01685 case PARTITION_STYLE_MBR:
01686 return FstubCreateDiskMBR(DeviceObject, &(Disk->Mbr));
01687 case PARTITION_STYLE_GPT:
01688 return FstubCreateDiskEFI(DeviceObject, &(Disk->Gpt));
01689 case PARTITION_STYLE_RAW:
01690 return FstubCreateDiskRaw(DeviceObject);
01691 default:
01692 return STATUS_NOT_SUPPORTED;
01693 }
01694 }
01695
01696
01697
01698
01699 NTSTATUS
01700 NTAPI
01701 IoGetBootDiskInformation(IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
01702 IN ULONG Size)
01703 {
01704 PIRP Irp;
01705 KEVENT Event;
01706 PLIST_ENTRY NextEntry;
01707 PFILE_OBJECT FileObject;
01708 DISK_GEOMETRY DiskGeometry;
01709 PDEVICE_OBJECT DeviceObject;
01710 UNICODE_STRING DeviceStringW;
01711 IO_STATUS_BLOCK IoStatusBlock;
01712 CHAR Buffer[128], ArcBuffer[128];
01713 NTSTATUS Status = STATUS_SUCCESS;
01714 BOOLEAN SingleDisk, IsBootDiskInfoEx;
01715 PARC_DISK_SIGNATURE ArcDiskSignature;
01716 PARC_DISK_INFORMATION ArcDiskInformation;
01717 PARTITION_INFORMATION_EX PartitionInformation;
01718 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
01719 ULONG DiskCount, DiskNumber, Signature, PartitionNumber;
01720 ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA;
01721 extern PLOADER_PARAMETER_BLOCK IopLoaderBlock;
01722 PAGED_CODE();
01723
01724
01725 if (!IopLoaderBlock)
01726 {
01727 return STATUS_TOO_LATE;
01728 }
01729
01730
01731 if (Size < sizeof(BOOTDISK_INFORMATION))
01732 {
01733 return STATUS_INVALID_PARAMETER;
01734 }
01735
01736
01737
01738
01739
01740
01741
01742
01743 ArcDiskInformation = IopLoaderBlock->ArcDiskInformation;
01744 SingleDisk = IsListEmpty(&(ArcDiskInformation->DiskSignatureListHead));
01745 IsBootDiskInfoEx = (Size >= sizeof(BOOTDISK_INFORMATION_EX));
01746 RtlInitAnsiString(&ArcBootString, IopLoaderBlock->ArcBootDeviceName);
01747 RtlInitAnsiString(&ArcSystemString, IopLoaderBlock->ArcHalDeviceName);
01748 DiskCount = IoGetConfigurationInformation()->DiskCount;
01749
01750
01751 if (DiskCount == 0)
01752 {
01753 return STATUS_SUCCESS;
01754 }
01755
01756
01757 for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
01758 {
01759
01760 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
01761 RtlInitAnsiString(&DeviceStringA, Buffer);
01762 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
01763 if (!NT_SUCCESS(Status))
01764 {
01765 continue;
01766 }
01767
01768
01769 Status = IoGetDeviceObjectPointer(&DeviceStringW,
01770 FILE_READ_ATTRIBUTES,
01771 &FileObject,
01772 &DeviceObject);
01773 RtlFreeUnicodeString(&DeviceStringW);
01774 if (!NT_SUCCESS(Status))
01775 {
01776 continue;
01777 }
01778
01779
01780 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
01781 DeviceObject,
01782 NULL,
01783 0,
01784 &DiskGeometry,
01785 sizeof(DISK_GEOMETRY),
01786 FALSE,
01787 &Event,
01788 &IoStatusBlock);
01789 if (!Irp)
01790 {
01791 ObDereferenceObject(FileObject);
01792 continue;
01793 }
01794
01795
01796 KeInitializeEvent(&Event, NotificationEvent, FALSE);
01797 Status = IoCallDriver(DeviceObject, Irp);
01798 if (Status == STATUS_PENDING)
01799 {
01800 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
01801 Status = IoStatusBlock.Status;
01802 }
01803 if (!NT_SUCCESS(Status))
01804 {
01805 ObDereferenceObject(FileObject);
01806 continue;
01807 }
01808
01809
01810 Status = IoReadPartitionTableEx(DeviceObject,
01811 &DriveLayout);
01812
01813
01814 ObDereferenceObject(FileObject);
01815
01816 if (!NT_SUCCESS(Status))
01817 {
01818 continue;
01819 }
01820
01821
01822 if (DiskGeometry.BytesPerSector < 512)
01823 {
01824 DiskGeometry.BytesPerSector = 512;
01825 }
01826
01827
01828 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
01829 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
01830 NextEntry = NextEntry->Flink)
01831 {
01832 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
01833 ARC_DISK_SIGNATURE,
01834 ListEntry);
01835
01836
01837
01838
01839
01840
01841 if (((SingleDisk && DiskCount == 1) ||
01842 (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature))) &&
01843 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR))
01844 {
01845
01846 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
01847 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
01848
01849
01850 for (PartitionNumber = 1; PartitionNumber <= DriveLayout->PartitionCount; PartitionNumber++)
01851 {
01852
01853 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", DiskNumber, PartitionNumber);
01854 RtlInitAnsiString(&DeviceStringA, Buffer);
01855 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
01856 if (!NT_SUCCESS(Status))
01857 {
01858 continue;
01859 }
01860
01861
01862 if (!Signature)
01863 {
01864 Signature = DriveLayout->Mbr.Signature;
01865 }
01866
01867
01868 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, PartitionNumber);
01869 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
01870
01871
01872 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
01873 {
01874
01875 BootDiskInformation->BootDeviceSignature = Signature;
01876
01877
01878 Status = IoGetDeviceObjectPointer(&DeviceStringW,
01879 FILE_READ_ATTRIBUTES,
01880 &FileObject,
01881 &DeviceObject);
01882 if (!NT_SUCCESS(Status))
01883 {
01884 RtlFreeUnicodeString(&DeviceStringW);
01885 continue;
01886 }
01887
01888
01889 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO_EX,
01890 DeviceObject,
01891 NULL,
01892 0,
01893 &PartitionInformation,
01894 sizeof(PARTITION_INFORMATION_EX),
01895 FALSE,
01896 &Event,
01897 &IoStatusBlock);
01898 if (!Irp)
01899 {
01900 ObDereferenceObject(FileObject);
01901 RtlFreeUnicodeString(&DeviceStringW);
01902 continue;
01903 }
01904
01905
01906 KeInitializeEvent(&Event, NotificationEvent, FALSE);
01907 Status = IoCallDriver(DeviceObject, Irp);
01908 if (Status == STATUS_PENDING)
01909 {
01910 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
01911 Status = IoStatusBlock.Status;
01912 }
01913 if (!NT_SUCCESS(Status))
01914 {
01915 ObDereferenceObject(FileObject);
01916 RtlFreeUnicodeString(&DeviceStringW);
01917 continue;
01918 }
01919
01920
01921 BootDiskInformation->BootPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
01922
01923
01924 if (IsBootDiskInfoEx)
01925 {
01926
01927 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
01928 {
01929 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceGuid = DriveLayout->Gpt.DiskId;
01930 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = TRUE;
01931 }
01932 else
01933 {
01934 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = FALSE;
01935 }
01936 }
01937
01938
01939 ObDereferenceObject(FileObject);
01940 }
01941
01942
01943 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
01944 {
01945
01946 BootDiskInformation->SystemDeviceSignature = Signature;
01947
01948
01949 Status = IoGetDeviceObjectPointer(&DeviceStringW,
01950 FILE_READ_ATTRIBUTES,
01951 &FileObject,
01952 &DeviceObject);
01953 if (!NT_SUCCESS(Status))
01954 {
01955 RtlFreeUnicodeString(&DeviceStringW);
01956 continue;
01957 }
01958
01959
01960 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO_EX,
01961 DeviceObject,
01962 NULL,
01963 0,
01964 &PartitionInformation,
01965 sizeof(PARTITION_INFORMATION_EX),
01966 FALSE,
01967 &Event,
01968 &IoStatusBlock);
01969 if (!Irp)
01970 {
01971 ObDereferenceObject(FileObject);
01972 RtlFreeUnicodeString(&DeviceStringW);
01973 continue;
01974 }
01975
01976
01977 KeInitializeEvent(&Event, NotificationEvent, FALSE);
01978 Status = IoCallDriver(DeviceObject, Irp);
01979 if (Status == STATUS_PENDING)
01980 {
01981 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
01982 Status = IoStatusBlock.Status;
01983 }
01984 if (!NT_SUCCESS(Status))
01985 {
01986 ObDereferenceObject(FileObject);
01987 RtlFreeUnicodeString(&DeviceStringW);
01988 continue;
01989 }
01990
01991
01992 BootDiskInformation->SystemPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
01993
01994
01995 if (IsBootDiskInfoEx)
01996 {
01997
01998 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
01999 {
02000 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceGuid = DriveLayout->Gpt.DiskId;
02001 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = TRUE;
02002 }
02003 else
02004 {
02005 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = FALSE;
02006 }
02007 }
02008
02009
02010 ObDereferenceObject(FileObject);
02011 }
02012
02013
02014 RtlFreeUnicodeString(&DeviceStringW);
02015 }
02016 }
02017 }
02018
02019
02020 ExFreePool(DriveLayout);
02021 }
02022
02023
02024 return Status;
02025 }
02026
02027
02028
02029
02030 NTSTATUS
02031 NTAPI
02032 IoReadDiskSignature(IN PDEVICE_OBJECT DeviceObject,
02033 IN ULONG BytesPerSector,
02034 OUT PDISK_SIGNATURE Signature)
02035 {
02036 PULONG Buffer;
02037 NTSTATUS Status;
02038 ULONG HeaderCRC32, i, CheckSum;
02039 PEFI_PARTITION_HEADER EFIHeader;
02040 PPARTITION_DESCRIPTOR PartitionDescriptor;
02041 PAGED_CODE();
02042
02043
02044 if (BytesPerSector < 512)
02045 {
02046 BytesPerSector = 512;
02047 }
02048
02049
02050 Buffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, BytesPerSector, TAG_FSTUB);
02051 if (!Buffer)
02052 {
02053 return STATUS_NO_MEMORY;
02054 }
02055
02056
02057 Status = FstubReadSector(DeviceObject,
02058 BytesPerSector,
02059 0ULL,
02060 (PUSHORT)Buffer);
02061 if (!NT_SUCCESS(Status))
02062 {
02063 goto Cleanup;
02064 }
02065
02066
02067 PartitionDescriptor = (PPARTITION_DESCRIPTOR)
02068 &(Buffer[PARTITION_TABLE_OFFSET]);
02069
02070 if (PartitionDescriptor[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
02071 PartitionDescriptor[1].PartitionType == 0 &&
02072 PartitionDescriptor[2].PartitionType == 0 &&
02073 PartitionDescriptor[3].PartitionType == 0)
02074 {
02075
02076 Status = FstubReadSector(DeviceObject,
02077 BytesPerSector,
02078 1ULL,
02079 (PUSHORT)Buffer);
02080 if (!NT_SUCCESS(Status))
02081 {
02082 goto Cleanup;
02083 }
02084 EFIHeader = (PEFI_PARTITION_HEADER)Buffer;
02085
02086
02087
02088
02089
02090 if (EFIHeader->Signature != EFI_HEADER_SIGNATURE ||
02091 EFIHeader->Revision != EFI_HEADER_REVISION_1 ||
02092 EFIHeader->HeaderSize != sizeof(EFI_PARTITION_HEADER))
02093 {
02094 Status = STATUS_DISK_CORRUPT_ERROR;
02095 goto Cleanup;
02096 }
02097
02098
02099 HeaderCRC32 = EFIHeader->HeaderCRC32;
02100
02101 EFIHeader->HeaderCRC32 = 0;
02102
02103 if (RtlComputeCrc32(0, (PUCHAR)Buffer, sizeof(EFI_PARTITION_HEADER)) != HeaderCRC32)
02104 {
02105 Status = STATUS_DISK_CORRUPT_ERROR;
02106 goto Cleanup;
02107 }
02108
02109
02110 Signature->PartitionStyle = PARTITION_STYLE_GPT;
02111 Signature->Gpt.DiskId = EFIHeader->DiskGUID;
02112 }
02113 else
02114 {
02115
02116 for (i = 0, CheckSum = 0; i < 512 / sizeof(ULONG) ; i++)
02117 {
02118 CheckSum += Buffer[i];
02119 }
02120
02121
02122 Signature->PartitionStyle = PARTITION_STYLE_MBR;
02123 Signature->Mbr.Signature = Buffer[PARTITION_TABLE_OFFSET / 2 - 1];
02124 Signature->Mbr.CheckSum = CheckSum;
02125 }
02126
02127 Cleanup:
02128
02129 ExFreePoolWithTag(Buffer, TAG_FSTUB);
02130 return Status;
02131 }
02132
02133
02134
02135
02136 NTSTATUS
02137 NTAPI
02138 IoReadPartitionTableEx(IN PDEVICE_OBJECT DeviceObject,
02139 IN struct _DRIVE_LAYOUT_INFORMATION_EX** DriveLayout)
02140 {
02141 NTSTATUS Status;
02142 PDISK_INFORMATION Disk;
02143 PARTITION_STYLE PartitionStyle;
02144 PAGED_CODE();
02145
02146 ASSERT(DeviceObject);
02147 ASSERT(DriveLayout);
02148
02149
02150 Status = FstubAllocateDiskInformation(DeviceObject, &Disk, 0);
02151 if (!NT_SUCCESS(Status))
02152 {
02153 return Status;
02154 }
02155 ASSERT(Disk);
02156
02157
02158 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
02159 if (!NT_SUCCESS(Status))
02160 {
02161 FstubFreeDiskInformation(Disk);
02162 return Status;
02163 }
02164
02165
02166 switch (PartitionStyle)
02167 {
02168 case PARTITION_STYLE_MBR:
02169 case PARTITION_STYLE_RAW:
02170 Status = FstubReadPartitionTableMBR(Disk, FALSE, DriveLayout);
02171 break;
02172
02173 case PARTITION_STYLE_GPT:
02174
02175 Status = FstubReadPartitionTableEFI(Disk, FALSE, DriveLayout);
02176
02177 if (!NT_SUCCESS(Status))
02178 {
02179 Status = FstubReadPartitionTableEFI(Disk, TRUE, DriveLayout);
02180 }
02181 break;
02182
02183 default:
02184 DPRINT("Unknown partition type\n");
02185 Status = STATUS_UNSUCCESSFUL;
02186 }
02187
02188
02189 FstubFreeDiskInformation(Disk);
02190
02191
02192 if (NT_SUCCESS(Status))
02193 {
02194 FstubDbgPrintDriveLayoutEx(*DriveLayout);
02195 }
02196
02197 return Status;
02198 }
02199
02200
02201
02202
02203 NTSTATUS
02204 NTAPI
02205 IoSetPartitionInformationEx(IN PDEVICE_OBJECT DeviceObject,
02206 IN ULONG PartitionNumber,
02207 IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo)
02208 {
02209 NTSTATUS Status;
02210 PDISK_INFORMATION Disk;
02211 PARTITION_STYLE PartitionStyle;
02212 PAGED_CODE();
02213
02214 ASSERT(DeviceObject);
02215 ASSERT(PartitionInfo);
02216
02217
02218 FstubDbgPrintSetPartitionEx(PartitionInfo, PartitionNumber);
02219
02220
02221 Status = FstubAllocateDiskInformation(DeviceObject, &Disk, NULL);
02222 if (!NT_SUCCESS(Status))
02223 {
02224 return Status;
02225 }
02226
02227
02228 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
02229 if (!NT_SUCCESS(Status))
02230 {
02231 FstubFreeDiskInformation(Disk);
02232 return Status;
02233 }
02234
02235
02236 if (PartitionInfo->PartitionStyle != PartitionStyle)
02237 {
02238 FstubFreeDiskInformation(Disk);
02239 return STATUS_INVALID_PARAMETER;
02240 }
02241
02242
02243 switch (PartitionStyle)
02244 {
02245 case PARTITION_STYLE_MBR:
02246 Status = IoSetPartitionInformation(DeviceObject,
02247 Disk->SectorSize,
02248 PartitionNumber,
02249 PartitionInfo->Mbr.PartitionType);
02250 break;
02251 case PARTITION_STYLE_GPT:
02252 Status = FstubSetPartitionInformationEFI(Disk,
02253 PartitionNumber,
02254 &(PartitionInfo->Gpt));
02255 break;
02256 default:
02257 Status = STATUS_NOT_SUPPORTED;
02258 }
02259
02260
02261 FstubFreeDiskInformation(Disk);
02262 return Status;
02263 }
02264
02265
02266
02267
02268 NTSTATUS
02269 NTAPI
02270 IoVerifyPartitionTable(IN PDEVICE_OBJECT DeviceObject,
02271 IN BOOLEAN FixErrors)
02272 {
02273 NTSTATUS Status;
02274 PDISK_INFORMATION Disk;
02275 PARTITION_STYLE PartitionStyle;
02276 PAGED_CODE();
02277
02278 ASSERT(DeviceObject);
02279
02280
02281 Status = FstubAllocateDiskInformation(DeviceObject, &Disk, NULL);
02282 if (!NT_SUCCESS(Status))
02283 {
02284 return Status;
02285 }
02286 ASSERT(Disk);
02287
02288
02289 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
02290 if (!NT_SUCCESS(Status))
02291 {
02292 FstubFreeDiskInformation(Disk);
02293 return Status;
02294 }
02295
02296
02297 switch (PartitionStyle)
02298 {
02299
02300 case PARTITION_STYLE_MBR:
02301 Status = STATUS_SUCCESS;
02302 break;
02303
02304 case PARTITION_STYLE_GPT:
02305 Status = FstubVerifyPartitionTableEFI(Disk, FixErrors);
02306 break;
02307
02308 default:
02309 Status = STATUS_NOT_SUPPORTED;
02310 }
02311
02312
02313 FstubFreeDiskInformation(Disk);
02314 return Status;
02315 }
02316
02317
02318
02319
02320 NTSTATUS
02321 NTAPI
02322 IoWritePartitionTableEx(IN PDEVICE_OBJECT DeviceObject,
02323 IN struct _DRIVE_LAYOUT_INFORMATION_EX* DriveLayout)
02324 {
02325 NTSTATUS Status;
02326 PDISK_INFORMATION Disk;
02327 ULONGLONG SectorsForPartitions;
02328 EFI_PARTITION_HEADER EfiHeader;
02329 PAGED_CODE();
02330
02331 ASSERT(DeviceObject);
02332 ASSERT(DriveLayout);
02333
02334
02335 FstubDbgPrintDriveLayoutEx(DriveLayout);
02336
02337
02338 Status = FstubAllocateDiskInformation(DeviceObject, &Disk, 0);
02339 if (!NT_SUCCESS(Status))
02340 {
02341 return Status;
02342 }
02343 ASSERT(Disk);
02344
02345 switch (DriveLayout->PartitionStyle)
02346 {
02347 case PARTITION_STYLE_MBR:
02348 Status = FstubWritePartitionTableMBR(Disk, DriveLayout);
02349 break;
02350
02351 case PARTITION_STYLE_GPT:
02352
02353 Status = FstubReadHeaderEFI(Disk,
02354 FALSE,
02355 &EfiHeader);
02356
02357 if (!NT_SUCCESS(Status))
02358 {
02359 Status = FstubReadHeaderEFI(Disk,
02360 TRUE,
02361 &EfiHeader);
02362 }
02363
02364
02365 if (NT_SUCCESS(Status))
02366 {
02367
02368 if (DriveLayout->PartitionCount <= EfiHeader.NumberOfEntries)
02369 {
02370
02371 SectorsForPartitions = (EfiHeader.NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
02372
02373 EfiHeader.FirstUsableLBA = SectorsForPartitions + 2;
02374
02375 EfiHeader.LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
02376
02377 Status = FstubWritePartitionTableEFI(Disk,
02378 EfiHeader.DiskGUID,
02379 EfiHeader.NumberOfEntries,
02380 EfiHeader.FirstUsableLBA,
02381 EfiHeader.LastUsableLBA,
02382 FALSE,
02383 DriveLayout->PartitionCount,
02384 DriveLayout->PartitionEntry);
02385
02386 if (NT_SUCCESS(Status))
02387 {
02388 Status = FstubWritePartitionTableEFI(Disk,
02389 EfiHeader.DiskGUID,
02390 EfiHeader.NumberOfEntries,
02391 EfiHeader.FirstUsableLBA,
02392 EfiHeader.LastUsableLBA,
02393 TRUE,
02394 DriveLayout->PartitionCount,
02395 DriveLayout->PartitionEntry);
02396 }
02397 }
02398 }
02399 break;
02400
02401 default:
02402 DPRINT("Unsupported partition style: %ld\n", DriveLayout->PartitionStyle);
02403 Status = STATUS_NOT_SUPPORTED;
02404 }
02405
02406
02407 FstubFreeDiskInformation(Disk);
02408
02409 return Status;
02410 }
02411
02412