ReactOS 0.4.16-dev-2206-gc56950d
uefidisk.c
Go to the documentation of this file.
1/*
2 * PROJECT: FreeLoader UEFI Support
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Disk Access Functions
5 * COPYRIGHT: Copyright 2022 Justin Miller <justinmiller100@gmail.com>
6 */
7
8/* INCLUDES ******************************************************************/
9
10#include <uefildr.h>
11
12#include <debug.h>
14
15#define TAG_HW_RESOURCE_LIST 'lRwH'
16#define TAG_HW_DISK_CONTEXT 'cDwH'
17#define FIRST_BIOS_DISK 0x80
18#define FIRST_PARTITION 1
19
20/* Maximum block size we support (8KB) - filters out flash devices */
21#define MAX_SUPPORTED_BLOCK_SIZE 8192
22
23/* GPT (GUID Partition Table) definitions */
24#define EFI_PARTITION_HEADER_SIGNATURE "EFI PART"
25#define EFI_HEADER_LOCATION 1ULL
26#define EFI_TABLE_REVISION 0x00010000
27#define EFI_PARTITION_ENTRIES_BLOCK 2ULL
28#define EFI_PARTITION_ENTRY_COUNT 128
29#define EFI_PARTITION_ENTRY_SIZE 128
30#define EFI_PARTITION_NAME_LENGTH 36
31
32/* GPT Partition Type GUIDs */
33#define EFI_PART_TYPE_UNUSED_GUID \
34 {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
35
36#define EFI_PART_TYPE_EFI_SYSTEM_PART_GUID \
37 {0xc12a7328, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b}}
38
39#include <pshpack1.h>
40
41/* GPT Table Header */
42typedef struct _GPT_TABLE_HEADER
43{
44 CHAR8 Signature[8]; /* "EFI PART" */
45 UINT32 Revision; /* 0x00010000 */
46 UINT32 HeaderSize; /* Size of header (usually 92) */
47 UINT32 HeaderCrc32; /* CRC32 of header */
48 UINT32 Reserved; /* Must be 0 */
49 UINT64 MyLba; /* LBA of this header */
50 UINT64 AlternateLba; /* LBA of alternate header */
51 UINT64 FirstUsableLba; /* First usable LBA for partitions */
52 UINT64 LastUsableLba; /* Last usable LBA for partitions */
53 EFI_GUID DiskGuid; /* Disk GUID */
54 UINT64 PartitionEntryLba; /* LBA of partition entries array */
55 UINT32 NumberOfPartitionEntries; /* Number of partition entries */
56 UINT32 SizeOfPartitionEntry; /* Size of each entry (usually 128) */
57 UINT32 PartitionEntryArrayCrc32; /* CRC32 of partition entries array */
59
60/* GPT Partition Entry */
62{
63 EFI_GUID PartitionTypeGuid; /* Partition type GUID */
64 EFI_GUID UniquePartitionGuid; /* Unique partition GUID */
65 UINT64 StartingLba; /* Starting LBA */
66 UINT64 EndingLba; /* Ending LBA */
67 UINT64 Attributes; /* Partition attributes */
68 CHAR16 PartitionName[EFI_PARTITION_NAME_LENGTH]; /* Partition name (UTF-16) */
70
71#include <poppack.h>
72
73typedef struct tagDISKCONTEXT
74{
81
82typedef struct _INTERNAL_UEFI_DISK
83{
90
91/* GLOBALS *******************************************************************/
92
95extern EFI_HANDLE PublicBootHandle; /* Freeldr itself */
96
97/* Made to match BIOS */
103
108
109static const CHAR Hex[] = "0123456789abcdef";
110static CHAR PcDiskIdentifier[32][20];
111
112/* UEFI-specific */
119
120static
123 IN PVOID Pointer,
125{
127
128 if (Alignment <= 1)
129 return TRUE;
130
131 Value = (ULONG_PTR)Pointer;
132 return ((Value & (Alignment - 1)) == 0);
133}
134
135static
139{
140 ULONG RequiredAlignment = (Alignment == 0) ? 1 : Alignment;
142
143 if (DiskReadBuffer != NULL && DiskReadBufferAlignment >= RequiredAlignment &&
144 UefiIsAlignedPointer(DiskReadBuffer, RequiredAlignment))
145 {
146 return TRUE;
147 }
148
149 DiskReadBufferAlignment = RequiredAlignment;
150
152 {
157 }
158
160 DiskReadBufferSize + RequiredAlignment,
161 (void**)&DiskReadBufferRaw);
163 {
164 ERR("Failed to allocate aligned disk read buffer (align %lu)\n", RequiredAlignment);
166 return FALSE;
167 }
169
171 if (!UefiIsAlignedPointer(DiskReadBuffer, RequiredAlignment))
172 {
173 ERR("Aligned disk read buffer is not properly aligned (align %lu)\n", RequiredAlignment);
174 return FALSE;
175 }
176
177 return TRUE;
178}
179
180/* FUNCTIONS *****************************************************************/
181
182PCHAR
184{
185 TRACE("GetHarddiskIdentifier: DriveNumber: %d\n", DriveNumber);
186 if (DriveNumber < FIRST_BIOS_DISK)
187 return NULL;
188 return PcDiskIdentifier[DriveNumber - FIRST_BIOS_DISK];
189}
190
191static LONG lReportError = 0; // >= 0: display errors; < 0: hide errors.
192
193LONG
195{
196 /* Set the reference count */
197 if (bShowError) ++lReportError;
198 else --lReportError;
199 return lReportError;
200}
201
202
203/* GPT Support Functions ******************************************************/
204
205static
208 IN UCHAR DriveNumber,
209 OUT PGPT_TABLE_HEADER GptHeader)
210{
211 ULONG ArcDriveIndex;
212 EFI_BLOCK_IO* BlockIo;
214 ULONG BlockSize;
215 ULONG IoAlign;
216 ULONGLONG HeaderLba = EFI_HEADER_LOCATION;
217
218 if (DriveNumber < FIRST_BIOS_DISK)
219 return FALSE;
220
221 ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK;
222 if (ArcDriveIndex >= PcBiosDiskCount || InternalUefiDisk == NULL)
223 return FALSE;
224
226 InternalUefiDisk[ArcDriveIndex].Handle,
228 (VOID**)&BlockIo);
229
230 if (EFI_ERROR(Status) || BlockIo == NULL)
231 return FALSE;
232
233 if (!BlockIo->Media->MediaPresent)
234 return FALSE;
235
236 BlockSize = BlockIo->Media->BlockSize;
237 IoAlign = BlockIo->Media->IoAlign;
238
240 {
241 ERR("Failed to align disk read buffer for drive %d\n", DriveNumber);
242 return FALSE;
243 }
244
245 /* Read GPT header from LBA 1 */
246 Status = BlockIo->ReadBlocks(
247 BlockIo,
248 BlockIo->Media->MediaId,
249 HeaderLba,
250 BlockSize,
252
253 if (EFI_ERROR(Status))
254 return FALSE;
255
256 RtlCopyMemory(GptHeader, DiskReadBuffer, sizeof(GPT_TABLE_HEADER));
257
258 /* Verify GPT signature */
259 if (memcmp(GptHeader->Signature, EFI_PARTITION_HEADER_SIGNATURE, 8) != 0)
260 return FALSE;
261
262 /* Verify revision */
263 if (GptHeader->Revision != EFI_TABLE_REVISION)
264 {
265 TRACE("GPT header has unsupported revision: 0x%x\n", GptHeader->Revision);
266 return FALSE;
267 }
268
269 return TRUE;
270}
271
274 IN UCHAR DriveNumber,
276 OUT PPARTITION_TABLE_ENTRY PartitionTableEntry)
277{
278 GPT_TABLE_HEADER GptHeader;
279 GPT_PARTITION_ENTRY GptEntry;
280 ULONG ArcDriveIndex;
281 EFI_BLOCK_IO* BlockIo;
283 ULONG BlockSize;
284 ULONGLONG EntryLba;
285 ULONG EntryOffset;
286 ULONG EntriesPerBlock;
288
289 if (DriveNumber < FIRST_BIOS_DISK)
290 return FALSE;
291
292 ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK;
293 if (ArcDriveIndex >= PcBiosDiskCount || InternalUefiDisk == NULL)
294 return FALSE;
295
296 /* Read GPT header */
297 if (!UefiReadGptHeader(DriveNumber, &GptHeader))
298 return FALSE;
299
300 /* Validate partition number */
302 return FALSE;
303
304 /* Convert to 0-based index */
305 ULONG EntryIndex = PartitionNumber - 1;
306
308 InternalUefiDisk[ArcDriveIndex].Handle,
310 (VOID**)&BlockIo);
311
312 if (EFI_ERROR(Status) || BlockIo == NULL)
313 return FALSE;
314
315 BlockSize = BlockIo->Media->BlockSize;
316 EntriesPerBlock = BlockSize / GptHeader.SizeOfPartitionEntry;
317 EntryLba = GptHeader.PartitionEntryLba + (EntryIndex / EntriesPerBlock);
318 EntryOffset = (EntryIndex % EntriesPerBlock) * GptHeader.SizeOfPartitionEntry;
319
320 /* Read the block containing the partition entry */
321 Status = BlockIo->ReadBlocks(
322 BlockIo,
323 BlockIo->Media->MediaId,
324 EntryLba,
325 BlockSize,
327
328 if (EFI_ERROR(Status))
329 return FALSE;
330
331 /* Extract partition entry */
332 RtlCopyMemory(&GptEntry, (PUCHAR)DiskReadBuffer + EntryOffset, sizeof(GPT_PARTITION_ENTRY));
333
334 /* Check if partition is unused */
335 if (memcmp(&GptEntry.PartitionTypeGuid, &UnusedGuid, sizeof(EFI_GUID)) == 0)
336 return FALSE;
337
338 /* Convert GPT entry to MBR-style PARTITION_TABLE_ENTRY */
339 RtlZeroMemory(PartitionTableEntry, sizeof(*PartitionTableEntry));
340
341 /* Calculate sector offset and count */
342 /* GPT uses LBA, convert to 512-byte sectors */
343 ULONGLONG StartLba = GptEntry.StartingLba;
344 ULONGLONG EndLba = GptEntry.EndingLba;
345 ULONGLONG SectorCount = (EndLba - StartLba + 1);
346
347 /* For GPT, we need to convert from device block size to 512-byte sectors */
348 ULONGLONG StartSector = (StartLba * BlockSize) / 512;
349 ULONGLONG SectorCount512 = (SectorCount * BlockSize) / 512;
350
351 PartitionTableEntry->SectorCountBeforePartition = (ULONG)StartSector;
352 PartitionTableEntry->PartitionSectorCount = (ULONG)SectorCount512;
353 PartitionTableEntry->SystemIndicator = PARTITION_GPT; /* Mark as GPT partition */
354
355 return TRUE;
356}
357
358static
361 IN UCHAR DriveNumber,
362 OUT PPARTITION_TABLE_ENTRY PartitionTableEntry,
363 OUT PULONG BootPartition)
364{
365 ULONG PartitionNum;
366 ULONG ArcDriveIndex;
367 EFI_BLOCK_IO* BootBlockIo;
369 ULONGLONG BootPartitionSize;
370 PARTITION_TABLE_ENTRY TempPartitionEntry;
371
372 TRACE("UefiGetBootPartitionEntry: DriveNumber: %d\n", DriveNumber - FIRST_BIOS_DISK);
373
374 if (DriveNumber < FIRST_BIOS_DISK)
375 return FALSE;
376
377 ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK;
378 if (ArcDriveIndex >= PcBiosDiskCount || handles == NULL || UefiBootRootIndex >= HandleCount)
379 return FALSE;
380
381 /* Get the boot handle's Block I/O protocol to determine partition offset/size */
385 (VOID**)&BootBlockIo);
386
387 if (EFI_ERROR(Status) || BootBlockIo == NULL)
388 {
389 ERR("Failed to get Block I/O protocol for boot handle\n");
390 return FALSE;
391 }
392
393 /* For logical partitions, UEFI Block I/O protocol starts at block 0 */
394 /* We need to find which partition it corresponds to by comparing sizes */
395 BootPartitionSize = BootBlockIo->Media->LastBlock + 1;
396
397 TRACE("Boot partition: Size=%llu blocks, BlockSize=%lu\n",
398 BootPartitionSize, BootBlockIo->Media->BlockSize);
399
400 /* If boot handle is the root device itself (not a logical partition) */
401 if (!BootBlockIo->Media->LogicalPartition)
402 {
403 TRACE("Boot handle is root device, using partition 0\n");
404 *BootPartition = 0;
405 if (PartitionTableEntry != NULL)
406 {
407 RtlZeroMemory(PartitionTableEntry, sizeof(*PartitionTableEntry));
408 }
409 return TRUE;
410 }
411
412 /* Boot handle is a logical partition - find matching partition entry */
413 /* Try to detect GPT first by reading GPT header */
414 GPT_TABLE_HEADER GptHeader;
415 BOOLEAN IsGpt = UefiReadGptHeader(DriveNumber, &GptHeader);
416
417 if (IsGpt)
418 {
419 /* For GPT, iterate through GPT partition entries */
420 GPT_TABLE_HEADER GptHeader;
421 GPT_PARTITION_ENTRY GptEntry;
422 ULONG ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK;
423 EFI_BLOCK_IO* RootBlockIo;
424 ULONG BlockSize;
425 ULONGLONG EntryLba;
426 ULONG EntryOffset;
427 ULONG EntriesPerBlock;
430
431 if (!UefiReadGptHeader(DriveNumber, &GptHeader))
432 {
433 ERR("Failed to read GPT header\n");
434 return FALSE;
435 }
436
438 InternalUefiDisk[ArcDriveIndex].Handle,
440 (VOID**)&RootBlockIo);
441
442 if (EFI_ERROR(Status) || RootBlockIo == NULL)
443 return FALSE;
444
445 BlockSize = RootBlockIo->Media->BlockSize;
446 EntriesPerBlock = BlockSize / GptHeader.SizeOfPartitionEntry;
447
448 /* Iterate through GPT partition entries */
449 for (ULONG i = 0; i < GptHeader.NumberOfPartitionEntries; i++)
450 {
451 EntryLba = GptHeader.PartitionEntryLba + (i / EntriesPerBlock);
452 EntryOffset = (i % EntriesPerBlock) * GptHeader.SizeOfPartitionEntry;
453
454 /* Read the block containing the partition entry */
455 Status = RootBlockIo->ReadBlocks(
456 RootBlockIo,
457 RootBlockIo->Media->MediaId,
458 EntryLba,
459 BlockSize,
461
462 if (EFI_ERROR(Status))
463 continue;
464
465 /* Extract partition entry */
466 RtlCopyMemory(&GptEntry, (PUCHAR)DiskReadBuffer + EntryOffset, sizeof(GPT_PARTITION_ENTRY));
467
468 /* Skip unused partitions */
469 if (memcmp(&GptEntry.PartitionTypeGuid, &UnusedGuid, sizeof(EFI_GUID)) == 0)
470 continue;
471
472 /* Calculate partition size in blocks */
473 ULONGLONG PartitionSizeBlocks = GptEntry.EndingLba - GptEntry.StartingLba + 1;
474
475 TRACE("GPT Partition %lu: StartLba=%llu, EndLba=%llu, SizeBlocks=%llu\n",
476 i + 1, GptEntry.StartingLba, GptEntry.EndingLba, PartitionSizeBlocks);
477
478 /* Match partition by size (within 1 block tolerance for rounding) */
479 if (PartitionSizeBlocks == BootPartitionSize ||
480 (PartitionSizeBlocks > 0 &&
481 (PartitionSizeBlocks - 1 <= BootPartitionSize &&
482 BootPartitionSize <= PartitionSizeBlocks + 1)))
483 {
484 TRACE("Found matching GPT partition %lu: Size matches (%llu blocks)\n",
485 i + 1, BootPartitionSize);
486
487 *BootPartition = i + 1; /* GPT partitions are 1-indexed */
488
489 /* Convert GPT entry to MBR-style entry for compatibility */
490 if (PartitionTableEntry != NULL)
491 {
492 RtlZeroMemory(PartitionTableEntry, sizeof(*PartitionTableEntry));
493 ULONGLONG StartSector = (GptEntry.StartingLba * BlockSize) / 512;
494 ULONGLONG SectorCount = (PartitionSizeBlocks * BlockSize) / 512;
495 PartitionTableEntry->SectorCountBeforePartition = (ULONG)StartSector;
496 PartitionTableEntry->PartitionSectorCount = (ULONG)SectorCount;
497 PartitionTableEntry->SystemIndicator = PARTITION_GPT;
498 }
499 return TRUE;
500 }
501 }
502 }
503 else
504 {
505 /* MBR partition matching */
506 PartitionNum = FIRST_PARTITION;
507 while (DiskGetPartitionEntry(DriveNumber, PartitionNum, &TempPartitionEntry))
508 {
509 ULONGLONG PartitionSizeSectors = TempPartitionEntry.PartitionSectorCount;
510 ULONGLONG PartitionSizeBlocks;
511
512 /* Convert partition size from MBR sectors (always 512 bytes) to UEFI blocks */
513 /* MBR partition table always uses 512-byte sectors per specification */
514 /* UEFI Block I/O protocol reports sizes in device's BlockSize bytes */
515 /* Compare in bytes to avoid rounding issues, then convert to boot partition's block size */
516 ULONGLONG PartitionSizeBytes = PartitionSizeSectors * 512ULL;
517 PartitionSizeBlocks = PartitionSizeBytes / BootBlockIo->Media->BlockSize;
518
519 TRACE("Partition %lu: SizeSectors=%llu, SizeBlocks=%llu\n",
520 PartitionNum, PartitionSizeSectors, PartitionSizeBlocks);
521
522 /* Match partition by size (within 1 block tolerance for rounding) */
523 if (PartitionSizeBlocks == BootPartitionSize ||
524 (PartitionSizeBlocks > 0 &&
525 (PartitionSizeBlocks - 1 <= BootPartitionSize &&
526 BootPartitionSize <= PartitionSizeBlocks + 1)))
527 {
528 TRACE("Found matching partition %lu: Size matches (%llu blocks)\n",
529 PartitionNum, BootPartitionSize);
530
531 *BootPartition = PartitionNum;
532 if (PartitionTableEntry != NULL)
533 {
534 RtlCopyMemory(PartitionTableEntry, &TempPartitionEntry, sizeof(*PartitionTableEntry));
535 }
536 return TRUE;
537 }
538
539 PartitionNum++;
540 }
541 }
542
543 /* If we couldn't find a match, check if it's a CD-ROM (special case) */
544 if (BootBlockIo->Media->RemovableMedia && BootBlockIo->Media->BlockSize == 2048)
545 {
546 TRACE("Boot device is CD-ROM, using partition 0xFF\n");
547 *BootPartition = 0xFF;
548 if (PartitionTableEntry != NULL)
549 {
550 RtlZeroMemory(PartitionTableEntry, sizeof(*PartitionTableEntry));
551 }
552 return TRUE;
553 }
554
555 /* Fallback: if we can't determine, use partition 1 */
556 ERR("Could not determine boot partition, using partition 1 as fallback\n");
557 PartitionNum = FIRST_PARTITION;
558 if (DiskGetPartitionEntry(DriveNumber, PartitionNum, &TempPartitionEntry))
559 {
560 *BootPartition = PartitionNum;
561 if (PartitionTableEntry != NULL)
562 {
563 RtlCopyMemory(PartitionTableEntry, &TempPartitionEntry, sizeof(*PartitionTableEntry));
564 }
565 return TRUE;
566 }
567
568 return FALSE;
569}
570
571static
574{
577 return ESUCCESS;
578}
579
580static
583{
586
587 /*
588 * The ARC specification mentions that for partitions, StartingAddress and
589 * EndingAddress are the start and end positions of the partition in terms
590 * of byte offsets from the start of the disk.
591 * CurrentAddress is the current offset into (i.e. relative to) the partition.
592 */
593 Information->StartingAddress.QuadPart = Context->SectorOffset * Context->SectorSize;
594 Information->EndingAddress.QuadPart = (Context->SectorOffset + Context->SectorCount) * Context->SectorSize;
595 Information->CurrentAddress.QuadPart = Context->SectorNumber * Context->SectorSize;
596
597 Information->Type = DiskPeripheral; /* No floppy for you for now... */
598
599 return ESUCCESS;
600}
601
602static
604UefiDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
605{
607 UCHAR DriveNumber;
608 ULONG DrivePartition, SectorSize;
611 ULONG ArcDriveIndex;
612 PARTITION_TABLE_ENTRY PartitionTableEntry;
613 EFI_BLOCK_IO* BlockIo;
615
616 TRACE("UefiDiskOpen: File ID: %p, Path: %s\n", FileId, Path);
617
618 if (DiskReadBufferSize == 0)
619 {
620 ERR("DiskOpen(): DiskReadBufferSize is 0, something is wrong.\n");
621 ASSERT(FALSE);
622 return ENOMEM;
623 }
624
625 if (!DissectArcPath(Path, NULL, &DriveNumber, &DrivePartition))
626 return EINVAL;
627
628 TRACE("Opening disk: DriveNumber: %d, DrivePartition: %d\n", DriveNumber, DrivePartition);
629
630 if (DriveNumber < FIRST_BIOS_DISK)
631 return EINVAL;
632
633 ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK;
634 if (ArcDriveIndex >= PcBiosDiskCount || InternalUefiDisk == NULL)
635 return EINVAL;
636
637 /* Get Block I/O protocol for this drive */
639 InternalUefiDisk[ArcDriveIndex].Handle,
641 (VOID**)&BlockIo);
642
643 if (EFI_ERROR(Status) || BlockIo == NULL)
644 {
645 ERR("Failed to get Block I/O protocol for drive %d\n", DriveNumber);
646 return EINVAL;
647 }
648
649 /* Check media is present */
650 if (!BlockIo->Media->MediaPresent)
651 {
652 ERR("Media not present for drive %d\n", DriveNumber);
653 return EINVAL;
654 }
655
656 SectorSize = BlockIo->Media->BlockSize;
657
658 if (DrivePartition != 0xff && DrivePartition != 0)
659 {
660 if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
661 return EINVAL;
662
663 SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
664 SectorCount = PartitionTableEntry.PartitionSectorCount;
665 }
666 else
667 {
668 GEOMETRY Geometry;
669 if (!MachDiskGetDriveGeometry(DriveNumber, &Geometry))
670 return EINVAL;
671
672 if (SectorSize != Geometry.BytesPerSector)
673 {
674 ERR("SectorSize (%lu) != Geometry.BytesPerSector (%lu), expect problems!\n",
675 SectorSize, Geometry.BytesPerSector);
676 }
677
678 SectorOffset = 0;
679 SectorCount = Geometry.Sectors;
680 }
681
683 if (!Context)
684 return ENOMEM;
685
686 Context->DriveNumber = DriveNumber;
687 Context->SectorSize = SectorSize;
688 Context->SectorOffset = SectorOffset;
689 Context->SectorCount = SectorCount;
690 Context->SectorNumber = 0;
692 return ESUCCESS;
693}
694
695static
698{
700 UCHAR* Ptr = (UCHAR*)Buffer;
701 ULONG Length, TotalSectors, MaxSectors, ReadSectors;
703 BOOLEAN ret;
704 EFI_BLOCK_IO* BlockIo;
706 ULONG ArcDriveIndex;
707
709
710
711 TotalSectors = (N + Context->SectorSize - 1) / Context->SectorSize;
712 MaxSectors = DiskReadBufferSize / Context->SectorSize;
713 SectorOffset = Context->SectorOffset + Context->SectorNumber;
714
715 // If MaxSectors is 0, this will lead to infinite loop.
716 // In release builds assertions are disabled, however we also have sanity checks in DiskOpen()
717 ASSERT(MaxSectors > 0);
718
719 if (MaxSectors == 0)
720 {
721 ERR("MaxSectors is 0, cannot read\n");
722 *Count = 0;
723 return EIO;
724 }
725
726 ArcDriveIndex = Context->DriveNumber - FIRST_BIOS_DISK;
727 if (ArcDriveIndex >= PcBiosDiskCount || InternalUefiDisk == NULL)
728 {
729 ERR("Invalid drive number %d\n", Context->DriveNumber);
730 *Count = 0;
731 return EINVAL;
732 }
733
734 /* Get Block I/O protocol */
736 InternalUefiDisk[ArcDriveIndex].Handle,
738 (VOID**)&BlockIo);
739
740 if (EFI_ERROR(Status) || BlockIo == NULL)
741 {
742 ERR("Failed to get Block I/O protocol\n");
743 *Count = 0;
744 return EIO;
745 }
746
748 {
749 ERR("Failed to align disk read buffer\n");
750 *Count = 0;
751 return EIO;
752 }
753
754 ret = TRUE;
755
756 while (TotalSectors)
757 {
758 ReadSectors = min(TotalSectors, MaxSectors);
759
760 Status = BlockIo->ReadBlocks(
761 BlockIo,
762 BlockIo->Media->MediaId,
764 ReadSectors * Context->SectorSize,
766
767 if (EFI_ERROR(Status))
768 {
769 ERR("ReadBlocks failed: Status = 0x%lx\n", (ULONG)Status);
770 ret = FALSE;
771 break;
772 }
773
774 Length = ReadSectors * Context->SectorSize;
775 Length = min(Length, N);
776
778
779 Ptr += Length;
780 N -= Length;
781 SectorOffset += ReadSectors;
782 TotalSectors -= ReadSectors;
783 }
784
786 Context->SectorNumber = SectorOffset - Context->SectorOffset;
787
788 return (ret ? ESUCCESS : EIO);
789}
790
791static
794{
796 LARGE_INTEGER NewPosition = *Position;
797
798 switch (SeekMode)
799 {
800 case SeekAbsolute:
801 break;
802 case SeekRelative:
803 NewPosition.QuadPart += (Context->SectorNumber * Context->SectorSize);
804 break;
805 default:
806 ASSERT(FALSE);
807 return EINVAL;
808 }
809
810 if (NewPosition.QuadPart & (Context->SectorSize - 1))
811 return EINVAL;
812
813 /* Convert in number of sectors */
814 NewPosition.QuadPart /= Context->SectorSize;
815
816 /* HACK: CDROMs may have a SectorCount of 0 */
817 if (Context->SectorCount != 0 && NewPosition.QuadPart >= Context->SectorCount)
818 return EINVAL;
819
820 Context->SectorNumber = NewPosition.QuadPart;
821 return ESUCCESS;
822}
823
824static const DEVVTBL UefiDiskVtbl =
825{
831};
832
833static
834VOID
836{
839 ULONG i;
840 ULONG Checksum;
842 BOOLEAN ValidPartitionTable;
843 CHAR ArcName[MAX_PATH];
844 PARTITION_TABLE_ENTRY PartitionTableEntry;
845 ULONG ArcDriveIndex;
847
848 ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK;
849 if (ArcDriveIndex >= 32)
850 return;
851
852 Identifier = PcDiskIdentifier[ArcDriveIndex];
853
854 /* Detect disk partition type */
855 DiskDetectPartitionType(DriveNumber);
856
857 /* Read the MBR */
858 if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer))
859 {
860 ERR("Reading MBR failed\n");
861 /* We failed, use a default identifier */
862 sprintf(Identifier, "BIOSDISK%d", ArcDriveIndex);
863 return;
864 }
865
868
869 Signature = Mbr->Signature;
870 TRACE("Signature: %x\n", Signature);
871
872 /* Calculate the MBR checksum */
873 Checksum = 0;
874 for (i = 0; i < 512 / sizeof(ULONG); i++)
875 {
876 Checksum += Buffer[i];
877 }
878 Checksum = ~Checksum + 1;
879 TRACE("Checksum: %x\n", Checksum);
880
881 ValidPartitionTable = (Mbr->MasterBootRecordMagic == 0xAA55);
882
883 /* Fill out the ARC disk block */
884 sprintf(ArcName, "multi(0)disk(0)rdisk(%u)", ArcDriveIndex);
885 AddReactOSArcDiskInfo(ArcName, Signature, Checksum, ValidPartitionTable);
886
887 sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(0)", ArcDriveIndex);
889
890 /* Add partitions */
893 while (DiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry))
894 {
895 if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED)
896 {
897 sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(%lu)", ArcDriveIndex, i);
899 }
900 i++;
901 }
903
904 if (ArcDriveIndex < PcBiosDiskCount && InternalUefiDisk != NULL)
905 {
906 InternalUefiDisk[ArcDriveIndex].NumOfPartitions = i;
907 }
908
909 /* Convert checksum and signature to identifier string */
910 Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
911 Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
912 Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
913 Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
914 Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
915 Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
916 Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
917 Identifier[7] = Hex[Checksum & 0x0F];
918 Identifier[8] = '-';
919 Identifier[9] = Hex[(Signature >> 28) & 0x0F];
920 Identifier[10] = Hex[(Signature >> 24) & 0x0F];
921 Identifier[11] = Hex[(Signature >> 20) & 0x0F];
922 Identifier[12] = Hex[(Signature >> 16) & 0x0F];
923 Identifier[13] = Hex[(Signature >> 12) & 0x0F];
924 Identifier[14] = Hex[(Signature >> 8) & 0x0F];
925 Identifier[15] = Hex[(Signature >> 4) & 0x0F];
926 Identifier[16] = Hex[Signature & 0x0F];
927 Identifier[17] = '-';
928 Identifier[18] = (ValidPartitionTable ? 'A' : 'X');
929 Identifier[19] = 0;
930 TRACE("Identifier: %s\n", Identifier);
931}
932
933static
934VOID
936{
937 ULONG BlockDeviceIndex;
938 ULONG SystemHandleCount;
940 ULONG i;
941 UINTN HandleSize = 0;
942 EFI_BLOCK_IO* BlockIo;
943
944 PcBiosDiskCount = 0;
946
947 /* Step 1: Get the size needed for handles buffer - no matter how it fails we're good */
951 NULL,
952 &HandleSize,
953 NULL);
954
955 if (HandleSize == 0)
956 {
957 ERR("Failed to get handle buffer size: Status = 0x%lx\n", (ULONG)Status);
958 return;
959 }
960
961 SystemHandleCount = HandleSize / sizeof(EFI_HANDLE);
962 if (SystemHandleCount == 0)
963 {
964 ERR("No block devices found\n");
965 return;
966 }
967
968 /* Step 2: Allocate buffer for handles */
970 if (handles == NULL)
971 {
972 ERR("Failed to allocate memory for handles\n");
973 return;
974 }
975
976 /* Step 3: Get actual handles */
980 NULL,
981 &HandleSize,
982 handles);
983
984 if (EFI_ERROR(Status))
985 {
986 ERR("Failed to locate block device handles: Status = 0x%lx\n", (ULONG)Status);
987 return;
988 }
989
990 HandleCount = SystemHandleCount;
991
992 /* Step 4: Allocate internal disk structure */
994 sizeof(INTERNAL_UEFI_DISK) * SystemHandleCount,
996
997 if (InternalUefiDisk == NULL)
998 {
999 ERR("Failed to allocate memory for internal disk structure\n");
1000 return;
1001 }
1002
1003 RtlZeroMemory(InternalUefiDisk, sizeof(INTERNAL_UEFI_DISK) * SystemHandleCount);
1004
1005 /* Step 5: Find boot handle and determine if it's a root device or partition */
1007 for (i = 0; i < SystemHandleCount; i++)
1008 {
1009 if (handles[i] == PublicBootHandle)
1010 {
1012 TRACE("Found boot handle at index %lu\n", i);
1013
1014 /* Check if boot handle is a root device or partition */
1016 handles[i],
1017 &BlockIoGuid,
1018 (VOID**)&BlockIo);
1019
1020 if (!EFI_ERROR(Status) && BlockIo != NULL)
1021 {
1022 TRACE("Boot handle: LogicalPartition=%s, RemovableMedia=%s, BlockSize=%lu\n",
1023 BlockIo->Media->LogicalPartition ? "TRUE" : "FALSE",
1024 BlockIo->Media->RemovableMedia ? "TRUE" : "FALSE",
1025 BlockIo->Media->BlockSize);
1026 }
1027 break;
1028 }
1029 }
1030
1031 /* Step 6: Enumerate root block devices (skip logical partitions) */
1032 BlockDeviceIndex = 0;
1033 for (i = 0; i < SystemHandleCount; i++)
1034 {
1036 handles[i],
1037 &BlockIoGuid,
1038 (VOID**)&BlockIo);
1039
1040 if (EFI_ERROR(Status))
1041 {
1042 TRACE("HandleProtocol failed for handle %lu: Status = 0x%lx\n", i, (ULONG)Status);
1043 continue;
1044 }
1045
1046 if (BlockIo == NULL)
1047 {
1048 TRACE("BlockIo is NULL for handle %lu\n", i);
1049 continue;
1050 }
1051
1052 if (!BlockIo->Media->MediaPresent)
1053 {
1054 TRACE("Media not present for handle %lu\n", i);
1055 continue;
1056 }
1057
1058 if (BlockIo->Media->BlockSize == 0)
1059 {
1060 TRACE("Invalid block size (0) for handle %lu\n", i);
1061 continue;
1062 }
1063
1064 /* Filter out devices with unusually large block sizes (flash devices) */
1065 if (BlockIo->Media->BlockSize > MAX_SUPPORTED_BLOCK_SIZE)
1066 {
1067 TRACE("Block size too large (%lu) for handle %lu, skipping\n",
1068 BlockIo->Media->BlockSize, i);
1069 continue;
1070 }
1071
1072 /* Logical partitions are handled separately by partition scanning */
1073 if (BlockIo->Media->LogicalPartition)
1074 {
1075 /* If boot handle is a logical partition, we need to find its parent root device */
1076 /* For now, we'll handle this after enumeration by matching handles */
1077 TRACE("Skipping logical partition handle %lu\n", i);
1078 continue;
1079 }
1080
1081 /* This is a root block device */
1082 TRACE("Found root block device at index %lu: BlockSize=%lu, LastBlock=%llu\n",
1083 i, BlockIo->Media->BlockSize, BlockIo->Media->LastBlock);
1084
1085 InternalUefiDisk[BlockDeviceIndex].ArcDriveNumber = BlockDeviceIndex;
1086 InternalUefiDisk[BlockDeviceIndex].UefiHandleIndex = i;
1087 InternalUefiDisk[BlockDeviceIndex].Handle = handles[i];
1088 InternalUefiDisk[BlockDeviceIndex].IsThisTheBootDrive = FALSE;
1089
1090 /* Check if this root device contains the boot partition */
1091 /* If boot handle is a logical partition, we need to find which root device it belongs to */
1092 /* For now, if boot handle index matches, mark it as boot device */
1093 if (i == UefiBootRootIndex)
1094 {
1095 InternalUefiDisk[BlockDeviceIndex].IsThisTheBootDrive = TRUE;
1096 PublicBootArcDisk = BlockDeviceIndex;
1097 TRACE("Boot device is at ARC drive index %lu (root device)\n", BlockDeviceIndex);
1098 }
1099
1100 /* Increment PcBiosDiskCount BEFORE calling GetHarddiskInformation
1101 * so that UefiDiskReadLogicalSectors can validate the drive number */
1102 PcBiosDiskCount = BlockDeviceIndex + 1;
1103
1104 TRACE("Calling GetHarddiskInformation for drive %d (BlockDeviceIndex=%lu)\n",
1105 BlockDeviceIndex + FIRST_BIOS_DISK, BlockDeviceIndex);
1106 if (!UefiEnsureDiskReadBufferAligned(BlockIo->Media->IoAlign))
1107 {
1108 ERR("Failed to align disk read buffer for drive %d\n", BlockDeviceIndex + FIRST_BIOS_DISK);
1109 return;
1110 }
1111
1112 GetHarddiskInformation(BlockDeviceIndex + FIRST_BIOS_DISK);
1113 BlockDeviceIndex++;
1114 }
1115
1116 /* Step 7: If boot handle was a logical partition, find its parent root device */
1118 {
1121 &BlockIoGuid,
1122 (VOID**)&BlockIo);
1123
1124 if (!EFI_ERROR(Status) && BlockIo != NULL && BlockIo->Media->LogicalPartition)
1125 {
1126 TRACE("Boot handle is a logical partition, searching for parent root device\n");
1127 TRACE("Boot partition: BlockSize=%lu, RemovableMedia=%s\n",
1128 BlockIo->Media->BlockSize,
1129 BlockIo->Media->RemovableMedia ? "TRUE" : "FALSE");
1130
1131 /* Find the root device that matches the boot partition's characteristics */
1132 /* For CD-ROMs: match BlockSize=2048 and RemovableMedia=TRUE */
1133 /* For hard disks: match BlockSize and find the root device before this partition */
1134 BOOLEAN FoundBootDevice = FALSE;
1135 for (i = 0; i < BlockDeviceIndex; i++)
1136 {
1137 EFI_BLOCK_IO* RootBlockIo;
1140 &BlockIoGuid,
1141 (VOID**)&RootBlockIo);
1142
1143 if (EFI_ERROR(Status) || RootBlockIo == NULL)
1144 continue;
1145
1146 /* For CD-ROM: match BlockSize=2048 and RemovableMedia */
1147 if (BlockIo->Media->BlockSize == 2048 && BlockIo->Media->RemovableMedia)
1148 {
1149 if (RootBlockIo->Media->BlockSize == 2048 &&
1150 RootBlockIo->Media->RemovableMedia &&
1151 !RootBlockIo->Media->LogicalPartition)
1152 {
1155 FoundBootDevice = TRUE;
1156 TRACE("Found CD-ROM boot device at ARC drive index %lu\n", i);
1157 break;
1158 }
1159 }
1160 /* For hard disk partitions: the root device should be before the partition handle */
1161 else if (InternalUefiDisk[i].UefiHandleIndex < UefiBootRootIndex)
1162 {
1163 /* Check if this root device is likely the parent */
1164 if (RootBlockIo->Media->BlockSize == BlockIo->Media->BlockSize &&
1165 !RootBlockIo->Media->LogicalPartition)
1166 {
1167 /* This might be the parent, but we need to be more certain */
1168 /* For now, use the last root device before the boot handle */
1171 FoundBootDevice = TRUE;
1172 TRACE("Found potential hard disk boot device at ARC drive index %lu\n", i);
1173 }
1174 }
1175 }
1176
1177 if (!FoundBootDevice && PcBiosDiskCount > 0)
1178 {
1181 TRACE("Could not determine boot device, assuming first drive\n");
1182 }
1183 }
1184 }
1185
1186 TRACE("Found %lu root block devices\n", PcBiosDiskCount);
1187}
1188
1189static
1190BOOLEAN
1192{
1193 EFI_BLOCK_IO* BootBlockIo = NULL;
1194 EFI_BLOCK_IO* RootBlockIo = NULL;
1196 ULONG ArcDriveIndex;
1197
1198 TRACE("UefiSetBootpath: Setting up boot path\n");
1199
1201 {
1202 ERR("Invalid boot root index\n");
1203 return FALSE;
1204 }
1205
1206 ArcDriveIndex = PublicBootArcDisk;
1207 if (ArcDriveIndex >= PcBiosDiskCount || InternalUefiDisk == NULL)
1208 {
1209 ERR("Invalid boot arc disk index\n");
1210 return FALSE;
1211 }
1212
1215 &BlockIoGuid,
1216 (VOID**)&BootBlockIo);
1217
1218 if (EFI_ERROR(Status) || BootBlockIo == NULL)
1219 {
1220 ERR("Failed to get Block I/O protocol for boot handle\n");
1221 return FALSE;
1222 }
1223
1225 InternalUefiDisk[ArcDriveIndex].Handle,
1226 &BlockIoGuid,
1227 (VOID**)&RootBlockIo);
1228
1229 if (EFI_ERROR(Status) || RootBlockIo == NULL)
1230 {
1231 ERR("Failed to get Block I/O protocol for boot root device\n");
1232 return FALSE;
1233 }
1234
1235 FrldrBootDrive = (FIRST_BIOS_DISK + ArcDriveIndex);
1236
1237 /* Check if booting from CD-ROM by checking the boot handle properties */
1238 /* CD-ROMs have BlockSize=2048 and RemovableMedia=TRUE */
1239 if (BootBlockIo->Media->RemovableMedia == TRUE && BootBlockIo->Media->BlockSize == 2048)
1240 {
1241 /* Boot Partition 0xFF is the magic value that indicates booting from CD-ROM */
1242 FrldrBootPartition = 0xFF;
1244 "multi(0)disk(0)cdrom(%u)", ArcDriveIndex);
1245 TRACE("Boot path set to CD-ROM: %s\n", FrLdrBootPath);
1246 }
1247 else
1248 {
1249 ULONG BootPartition;
1250 PARTITION_TABLE_ENTRY PartitionEntry;
1251
1252 /* This is a hard disk */
1253 /* If boot handle is a logical partition, we need to determine which partition number */
1254 if (BootBlockIo->Media->LogicalPartition)
1255 {
1256 /* For logical partitions, we need to find the partition number */
1257 /* This is tricky - we'll use partition 1 as default for now */
1258 /* TODO: Properly determine partition number from boot handle */
1259 BootPartition = FIRST_PARTITION;
1260 TRACE("Boot handle is logical partition, using partition %lu\n", BootPartition);
1261 }
1262 else
1263 {
1264 /* Boot handle is the root device itself */
1265 if (!UefiGetBootPartitionEntry(FrldrBootDrive, &PartitionEntry, &BootPartition))
1266 {
1267 ERR("Failed to get boot partition entry\n");
1268 return FALSE;
1269 }
1270 }
1271
1273 "multi(0)disk(0)rdisk(%u)partition(%lu)",
1274 ArcDriveIndex, BootPartition);
1275 TRACE("Boot path set to hard disk: %s\n", FrLdrBootPath);
1276 }
1277
1278 return TRUE;
1279}
1280
1281BOOLEAN
1283{
1284 EFI_BLOCK_IO* BlockIo;
1286 ULONG ArcDriveIndex;
1288 PULONG Buffer;
1289 ULONG Checksum = 0;
1291 ULONG i;
1292
1299 {
1300 ERR("Failed to allocate disk read buffer\n");
1301 return FALSE;
1302 }
1303
1305
1306 if (PcBiosDiskCount == 0)
1307 {
1308 ERR("No block devices found\n");
1309 return FALSE;
1310 }
1311
1312 if (!UefiSetBootpath())
1313 {
1314 ERR("Failed to set boot path\n");
1315 return FALSE;
1316 }
1317
1318 /* Handle CD-ROM boot device registration */
1319 ArcDriveIndex = PublicBootArcDisk;
1320 if (ArcDriveIndex >= PcBiosDiskCount || InternalUefiDisk == NULL)
1321 {
1322 ERR("Invalid boot arc disk index\n");
1323 return FALSE;
1324 }
1325
1327 InternalUefiDisk[ArcDriveIndex].Handle,
1328 &BlockIoGuid,
1329 (VOID**)&BlockIo);
1330
1331 if (EFI_ERROR(Status) || BlockIo == NULL)
1332 {
1333 ERR("Failed to get Block I/O protocol\n");
1334 return FALSE;
1335 }
1336
1337 if (BlockIo->Media->RemovableMedia == TRUE && BlockIo->Media->BlockSize == 2048)
1338 {
1339 /* Read the MBR from CD-ROM (sector 16) */
1341 {
1342 ERR("Reading MBR from CD-ROM failed\n");
1343 return FALSE;
1344 }
1345
1348
1349 Signature = Mbr->Signature;
1350 TRACE("CD-ROM Signature: %x\n", Signature);
1351
1352 /* Calculate the MBR checksum */
1353 for (i = 0; i < 2048 / sizeof(ULONG); i++)
1354 {
1355 Checksum += Buffer[i];
1356 }
1357 Checksum = ~Checksum + 1;
1358 TRACE("CD-ROM Checksum: %x\n", Checksum);
1359
1360 /* Fill out the ARC disk block */
1362
1364 TRACE("Registered CD-ROM boot device: 0x%02X\n", (int)FrldrBootDrive);
1365 }
1366
1367 return TRUE;
1368}
1369
1370UCHAR
1372{
1373 /* No floppy support in UEFI */
1374 return 0;
1375}
1376
1377BOOLEAN
1379 IN UCHAR DriveNumber,
1380 IN ULONGLONG SectorNumber,
1383{
1384 ULONG ArcDriveIndex;
1385 EFI_BLOCK_IO* BlockIo;
1387 ULONG BlockSize;
1388 ULONG IoAlign;
1389
1390 if (DriveNumber < FIRST_BIOS_DISK)
1391 return FALSE;
1392
1393 ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK;
1394
1395 if (InternalUefiDisk == NULL)
1396 {
1397 ERR("InternalUefiDisk not initialized\n");
1398 return FALSE;
1399 }
1400
1401 if (ArcDriveIndex >= 32)
1402 {
1403 ERR("Drive index out of bounds: %d (ArcDriveIndex=%lu)\n", DriveNumber, ArcDriveIndex);
1404 return FALSE;
1405 }
1406
1407 /* Allow access during initialization: check if handle is set up */
1408 /* During initialization, Handle is set before GetHarddiskInformation is called */
1409 if (InternalUefiDisk[ArcDriveIndex].Handle == NULL)
1410 {
1411 ERR("Invalid drive number: %d (ArcDriveIndex=%lu, PcBiosDiskCount=%lu, Handle=NULL)\n",
1412 DriveNumber, ArcDriveIndex, PcBiosDiskCount);
1413 return FALSE;
1414 }
1415
1417 InternalUefiDisk[ArcDriveIndex].Handle,
1418 &BlockIoGuid,
1419 (VOID**)&BlockIo);
1420
1421 if (EFI_ERROR(Status) || BlockIo == NULL)
1422 {
1423 ERR("Failed to get Block I/O protocol for drive %d\n", DriveNumber);
1424 return FALSE;
1425 }
1426
1427 if (!BlockIo->Media->MediaPresent)
1428 {
1429 ERR("Media not present for drive %d\n", DriveNumber);
1430 return FALSE;
1431 }
1432
1433 BlockSize = BlockIo->Media->BlockSize;
1434 IoAlign = BlockIo->Media->IoAlign;
1435
1436 if (!UefiEnsureDiskReadBufferAligned(IoAlign))
1437 {
1438 ERR("Failed to align disk read buffer for drive %d\n", DriveNumber);
1439 return FALSE;
1440 }
1441
1442 if (!UefiIsAlignedPointer(Buffer, (IoAlign == 0) ? 1 : IoAlign))
1443 {
1444 ULONG TotalSectors = SectorCount;
1445 ULONG MaxSectors = DiskReadBufferSize / BlockSize;
1446 ULONGLONG CurrentSector = SectorNumber;
1447 PUCHAR OutPtr = (PUCHAR)Buffer;
1448
1449 if (MaxSectors == 0)
1450 {
1451 ERR("DiskReadBufferSize too small for block size %lu\n", BlockSize);
1452 return FALSE;
1453 }
1454
1455 while (TotalSectors)
1456 {
1457 ULONG ReadSectors = min(TotalSectors, MaxSectors);
1458 UINTN ReadSize = ReadSectors * BlockSize;
1459
1460 Status = BlockIo->ReadBlocks(
1461 BlockIo,
1462 BlockIo->Media->MediaId,
1463 CurrentSector,
1464 ReadSize,
1466
1467 if (EFI_ERROR(Status))
1468 {
1469 ERR("ReadBlocks failed: DriveNumber=%d, SectorNumber=%llu, SectorCount=%lu, Status=0x%lx\n",
1470 DriveNumber, CurrentSector, ReadSectors, (ULONG)Status);
1471 ERR("ReadBlocks details: BlockSize=%lu, IoAlign=%lu, Buffer=%p, DiskReadBuffer=%p, MediaId=0x%lx\n",
1472 BlockSize, IoAlign, Buffer, DiskReadBuffer, (ULONG)BlockIo->Media->MediaId);
1473 ERR("ReadBlocks media: LastBlock=%llu, LogicalPartition=%s, RemovableMedia=%s\n",
1474 BlockIo->Media->LastBlock,
1475 BlockIo->Media->LogicalPartition ? "TRUE" : "FALSE",
1476 BlockIo->Media->RemovableMedia ? "TRUE" : "FALSE");
1477 return FALSE;
1478 }
1479
1480 RtlCopyMemory(OutPtr, DiskReadBuffer, ReadSize);
1481 OutPtr += ReadSize;
1482 CurrentSector += ReadSectors;
1483 TotalSectors -= ReadSectors;
1484 }
1485
1486 return TRUE;
1487 }
1488
1489 Status = BlockIo->ReadBlocks(
1490 BlockIo,
1491 BlockIo->Media->MediaId,
1492 SectorNumber,
1493 SectorCount * BlockSize,
1494 Buffer);
1495
1496 if (EFI_ERROR(Status))
1497 {
1498 ERR("ReadBlocks failed: DriveNumber=%d, SectorNumber=%llu, SectorCount=%lu, Status=0x%lx\n",
1499 DriveNumber, SectorNumber, SectorCount, (ULONG)Status);
1500 ERR("ReadBlocks details: BlockSize=%lu, IoAlign=%lu, Buffer=%p, DiskReadBuffer=%p, MediaId=0x%lx\n",
1501 BlockSize, IoAlign, Buffer, DiskReadBuffer, (ULONG)BlockIo->Media->MediaId);
1502 ERR("ReadBlocks media: LastBlock=%llu, LogicalPartition=%s, RemovableMedia=%s\n",
1503 BlockIo->Media->LastBlock,
1504 BlockIo->Media->LogicalPartition ? "TRUE" : "FALSE",
1505 BlockIo->Media->RemovableMedia ? "TRUE" : "FALSE");
1506 return FALSE;
1507 }
1508
1509 return TRUE;
1510}
1511
1512BOOLEAN
1514{
1515 ULONG ArcDriveIndex;
1516 EFI_BLOCK_IO* BlockIo;
1518
1519 if (DriveNumber < FIRST_BIOS_DISK)
1520 return FALSE;
1521
1522 ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK;
1523
1524 if (InternalUefiDisk == NULL)
1525 {
1526 ERR("InternalUefiDisk not initialized\n");
1527 return FALSE;
1528 }
1529
1530 if (ArcDriveIndex >= 32 || InternalUefiDisk[ArcDriveIndex].Handle == NULL)
1531 {
1532 ERR("Invalid drive number: %d\n", DriveNumber);
1533 return FALSE;
1534 }
1535
1537 InternalUefiDisk[ArcDriveIndex].Handle,
1538 &BlockIoGuid,
1539 (VOID**)&BlockIo);
1540
1541 if (EFI_ERROR(Status) || BlockIo == NULL)
1542 {
1543 ERR("Failed to get Block I/O protocol for drive %d\n", DriveNumber);
1544 return FALSE;
1545 }
1546
1547 if (!BlockIo->Media->MediaPresent)
1548 {
1549 ERR("Media not present for drive %d\n", DriveNumber);
1550 return FALSE;
1551 }
1552
1553 Geometry->Cylinders = 1; /* Not relevant for UEFI Block I/O protocol */
1554 Geometry->Heads = 1; /* Not relevant for UEFI Block I/O protocol */
1555 Geometry->SectorsPerTrack = (ULONG)(BlockIo->Media->LastBlock + 1);
1556 Geometry->BytesPerSector = BlockIo->Media->BlockSize;
1557 Geometry->Sectors = BlockIo->Media->LastBlock + 1;
1558
1559 return TRUE;
1560}
1561
1562ULONG
1564{
1565 ULONG ArcDriveIndex;
1566 EFI_BLOCK_IO* BlockIo;
1568
1569 if (DriveNumber < FIRST_BIOS_DISK)
1570 return 0;
1571
1572 ArcDriveIndex = DriveNumber - FIRST_BIOS_DISK;
1573
1574 if (InternalUefiDisk == NULL)
1575 {
1576 ERR("InternalUefiDisk not initialized\n");
1577 return 0;
1578 }
1579
1580 if (ArcDriveIndex >= 32 || InternalUefiDisk[ArcDriveIndex].Handle == NULL)
1581 {
1582 ERR("Invalid drive number: %d\n", DriveNumber);
1583 return 0;
1584 }
1585
1587 InternalUefiDisk[ArcDriveIndex].Handle,
1588 &BlockIoGuid,
1589 (VOID**)&BlockIo);
1590
1591 if (EFI_ERROR(Status) || BlockIo == NULL)
1592 {
1593 ERR("Failed to get Block I/O protocol for drive %d\n", DriveNumber);
1594 return 0;
1595 }
1596
1597 if (!BlockIo->Media->MediaPresent)
1598 {
1599 ERR("Media not present for drive %d\n", DriveNumber);
1600 return 0;
1601 }
1602
1603 return (ULONG)(BlockIo->Media->LastBlock + 1);
1604}
#define N
Definition: crc32.c:57
#define BLOCK_IO_PROTOCOL
Definition: BlockIo.h:31
#define WARNING
Definition: BusLogic958.h:56
unsigned char BOOLEAN
unsigned long long UINT64
unsigned short CHAR16
signed char CHAR8
UINT32 UINTN
unsigned int UINT32
PRTL_UNICODE_STRING_BUFFER Path
#define EFI_PAGE_SIZE
Definition: UefiBaseType.h:189
#define EFI_ERROR(A)
Definition: UefiBaseType.h:165
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:31
VOID * EFI_HANDLE
Definition: UefiBaseType.h:35
@ EfiLoaderData
@ ByProtocol
Definition: UefiSpec.h:1428
VOID AddReactOSArcDiskInfo(IN PSTR ArcName, IN ULONG Signature, IN ULONG Checksum, IN BOOLEAN ValidPartitionTable)
Definition: archwsup.c:77
@ Identifier
Definition: asmpp.cpp:95
#define ERR(fmt,...)
Definition: precomp.h:57
BOOLEAN DissectArcPath(IN PCSTR ArcPath, OUT PCSTR *Path OPTIONAL, OUT PUCHAR DriveNumber, OUT PULONG PartitionNumber)
Definition: arcname.c:25
BOOLEAN DiskGetPartitionEntry(IN UCHAR DriveNumber, IN ULONG PartitionNumber, OUT PPARTITION_TABLE_ENTRY PartitionTableEntry)
Definition: partition.c:407
VOID DiskDetectPartitionType(IN UCHAR DriveNumber)
Definition: partition.c:314
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:71
struct _MASTER_BOOT_RECORD * PMASTER_BOOT_RECORD
#define PARTITION_GPT
Definition: disk.h:90
PVOID FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:709
VOID FsSetDeviceSpecific(ULONG FileId, PVOID Specific)
Definition: fs.c:702
VOID FsRegisterDevice(_In_ PCSTR DeviceName, _In_ const DEVVTBL *FuncTable)
Definition: fs.c:673
#define MachDiskGetDriveGeometry(Drive, Geom)
Definition: machine.h:122
#define MachDiskReadLogicalSectors(Drive, Start, Count, Buf)
Definition: machine.h:120
VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: heap.c:553
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: heap.c:545
#define SectorOffset(L)
Definition: cdprocs.h:1622
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define MAX_PATH
Definition: compat.h:34
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
#define EINVAL
Definition: errno.h:44
#define ENOMEM
Definition: errno.h:35
#define EIO
Definition: errno.h:28
static const WCHAR Signature[]
Definition: parser.c:141
return ret
Definition: mutex.c:146
#define ULONG_PTR
Definition: config.h:101
CCHAR FrLdrBootPath[MAX_PATH]
Definition: freeldr.c:29
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ASSERT(a)
Definition: mode.c:44
#define sprintf
Definition: sprintf.c:45
#define ULL(a, b)
Definition: format_msg.c:27
#define min(a, b)
Definition: monoChain.cc:55
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTRSAFEVAPI RtlStringCbPrintfA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1148
ULONG SectorCount
Definition: part_xbox.c:31
long LONG
Definition: pedump.c:60
@ ESUCCESS
Definition: arc.h:32
@ LoaderFirmwareTemporary
Definition: arc.h:298
ULONG ARC_STATUS
Definition: arc.h:4
@ DiskPeripheral
Definition: arc.h:138
@ SeekRelative
Definition: arc.h:60
@ SeekAbsolute
Definition: arc.h:59
enum _OPENMODE OPENMODE
enum _SEEKMODE SEEKMODE
#define TRACE(s)
Definition: solgame.cpp:4
BOOLEAN RemovableMedia
Definition: BlockIo.h:143
BOOLEAN LogicalPartition
Definition: BlockIo.h:156
UINT32 BlockSize
Definition: BlockIo.h:173
EFI_LBA LastBlock
Definition: BlockIo.h:184
BOOLEAN MediaPresent
Definition: BlockIo.h:150
EFI_FREE_POOL FreePool
Definition: UefiSpec.h:1814
EFI_LOCATE_HANDLE LocateHandle
Definition: UefiSpec.h:1835
EFI_HANDLE_PROTOCOL HandleProtocol
Definition: UefiSpec.h:1832
EFI_ALLOCATE_POOL AllocatePool
Definition: UefiSpec.h:1813
EFI_BOOT_SERVICES * BootServices
Definition: UefiSpec.h:1959
Definition: parttest.c:75
ULONG PartitionSectorCount
Definition: parttest.c:85
ULONG SectorCountBeforePartition
Definition: parttest.c:84
UCHAR SystemIndicator
Definition: parttest.c:80
EFI_BLOCK_IO_MEDIA * Media
Definition: BlockIo.h:230
EFI_BLOCK_READ ReadBlocks
Definition: BlockIo.h:233
Definition: disk.h:26
ULONG BytesPerSector
Number of bytes per sector.
Definition: disk.h:30
ULONG Cylinders
Number of cylinders on the disk.
Definition: disk.h:27
ULONGLONG Sectors
Total number of disk sectors/LBA blocks.
Definition: disk.h:31
ULONG SectorsPerTrack
Number of sectors per track.
Definition: disk.h:29
ULONG Heads
Number of heads on the disk.
Definition: disk.h:28
Definition: uefidisk.c:62
UINT64 EndingLba
Definition: uefidisk.c:66
EFI_GUID PartitionTypeGuid
Definition: uefidisk.c:63
EFI_GUID UniquePartitionGuid
Definition: uefidisk.c:64
UINT64 Attributes
Definition: uefidisk.c:67
CHAR16 PartitionName[EFI_PARTITION_NAME_LENGTH]
Definition: uefidisk.c:68
UINT64 StartingLba
Definition: uefidisk.c:65
UINT64 FirstUsableLba
Definition: uefidisk.c:51
UINT64 LastUsableLba
Definition: uefidisk.c:52
UINT32 Revision
Definition: uefidisk.c:45
UINT32 NumberOfPartitionEntries
Definition: uefidisk.c:55
UINT32 SizeOfPartitionEntry
Definition: uefidisk.c:56
UINT32 HeaderSize
Definition: uefidisk.c:46
UINT32 PartitionEntryArrayCrc32
Definition: uefidisk.c:57
CHAR8 Signature[8]
Definition: uefidisk.c:44
UINT32 HeaderCrc32
Definition: uefidisk.c:47
UINT64 PartitionEntryLba
Definition: uefidisk.c:54
EFI_GUID DiskGuid
Definition: uefidisk.c:53
UINT32 Reserved
Definition: uefidisk.c:48
UINT64 AlternateLba
Definition: uefidisk.c:50
BOOLEAN IsThisTheBootDrive
Definition: uefidisk.c:87
ULONG UefiHandleIndex
Definition: uefidisk.c:86
UCHAR ArcDriveNumber
Definition: uefidisk.c:84
EFI_HANDLE Handle
Definition: uefidisk.c:88
UCHAR NumOfPartitions
Definition: uefidisk.c:85
USHORT MasterBootRecordMagic
Definition: disk.h:63
ULONG Signature
Definition: disk.h:60
Definition: disk.h:40
Definition: fs.h:25
ULONGLONG SectorOffset
Definition: hwdisk.c:39
UCHAR DriveNumber
Definition: hwdisk.c:36
ULONGLONG SectorCount
Definition: hwdisk.c:40
ULONGLONG SectorNumber
Definition: hwdisk.c:41
ULONG SectorSize
Definition: hwdisk.c:38
static COORD Position
Definition: mouse.c:34
uint32_t * PULONG
Definition: typedefs.h:59
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define EFI_PARTITION_HEADER_SIGNATURE
Definition: uefidisk.c:24
#define EFI_PARTITION_NAME_LENGTH
Definition: uefidisk.c:30
static LONG lReportError
Definition: uefidisk.c:191
static ULONG PublicBootArcDisk
Definition: uefidisk.c:114
BOOLEAN UefiDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
Definition: uefidisk.c:1513
PVOID Buffer
Definition: uefidisk.c:107
static BOOLEAN UefiReadGptHeader(IN UCHAR DriveNumber, OUT PGPT_TABLE_HEADER GptHeader)
Definition: uefidisk.c:207
#define TAG_HW_DISK_CONTEXT
Definition: uefidisk.c:16
static BOOLEAN UefiGetBootPartitionEntry(IN UCHAR DriveNumber, OUT PPARTITION_TABLE_ENTRY PartitionTableEntry, OUT PULONG BootPartition)
Definition: uefidisk.c:360
PVOID DiskReadBuffer
Definition: uefidisk.c:98
BOOLEAN UefiDiskReadLogicalSectors(IN UCHAR DriveNumber, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: uefidisk.c:1378
struct tagDISKCONTEXT DISKCONTEXT
static BOOLEAN DiskReadBufferFromPool
Definition: uefidisk.c:101
struct _GPT_PARTITION_ENTRY GPT_PARTITION_ENTRY
static CHAR PcDiskIdentifier[32][20]
Definition: uefidisk.c:110
static EFI_GUID BlockIoGuid
Definition: uefidisk.c:116
BOOLEAN UefiInitializeBootDevices(VOID)
Definition: uefidisk.c:1282
static ARC_STATUS UefiDiskGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: uefidisk.c:582
#define EFI_TABLE_REVISION
Definition: uefidisk.c:26
#define EFI_PART_TYPE_UNUSED_GUID
Definition: uefidisk.c:33
EFI_HANDLE PublicBootHandle
Definition: uefimem.c:38
static ULONG DiskReadBufferAlignment
Definition: uefidisk.c:100
EFI_SYSTEM_TABLE * GlobalSystemTable
Definition: uefildr.c:16
LONG DiskReportError(BOOLEAN bShowError)
Definition: uefidisk.c:194
static const DEVVTBL UefiDiskVtbl
Definition: uefidisk.c:824
static BOOLEAN UefiEnsureDiskReadBufferAligned(IN ULONG Alignment)
Definition: uefidisk.c:137
static VOID UefiSetupBlockDevices(VOID)
Definition: uefidisk.c:935
struct _GPT_TABLE_HEADER GPT_TABLE_HEADER
#define EFI_HEADER_LOCATION
Definition: uefidisk.c:25
static const CHAR Hex[]
Definition: uefidisk.c:109
BOOLEAN UefiGetGptPartitionEntry(IN UCHAR DriveNumber, IN ULONG PartitionNumber, OUT PPARTITION_TABLE_ENTRY PartitionTableEntry)
Definition: uefidisk.c:273
struct _GPT_TABLE_HEADER * PGPT_TABLE_HEADER
static ULONG UefiBootRootIndex
Definition: uefidisk.c:113
static PVOID DiskReadBufferRaw
Definition: uefidisk.c:99
#define FIRST_BIOS_DISK
Definition: uefidisk.c:17
#define MAX_SUPPORTED_BLOCK_SIZE
Definition: uefidisk.c:21
static ARC_STATUS UefiDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: uefidisk.c:604
static ARC_STATUS UefiDiskSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: uefidisk.c:793
static INTERNAL_UEFI_DISK * InternalUefiDisk
Definition: uefidisk.c:115
static ARC_STATUS UefiDiskClose(ULONG FileId)
Definition: uefidisk.c:573
static VOID GetHarddiskInformation(UCHAR DriveNumber)
Definition: uefidisk.c:835
PCHAR GetHarddiskIdentifier(UCHAR DriveNumber)
Definition: uefidisk.c:183
static ARC_STATUS UefiDiskRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: uefidisk.c:697
static ULONG HandleCount
Definition: uefidisk.c:118
EFI_HANDLE GlobalImageHandle
Definition: uefildr.c:15
struct _INTERNAL_UEFI_DISK INTERNAL_UEFI_DISK
UCHAR PcBiosDiskCount
Definition: uefidisk.c:102
static EFI_HANDLE * handles
Definition: uefidisk.c:117
UCHAR UefiGetFloppyCount(VOID)
Definition: uefidisk.c:1371
SIZE_T DiskReadBufferSize
Definition: uefidisk.c:106
struct _GPT_PARTITION_ENTRY * PGPT_PARTITION_ENTRY
static BOOLEAN UefiIsAlignedPointer(IN PVOID Pointer, IN ULONG Alignment)
Definition: uefidisk.c:122
ULONG UefiDiskGetCacheableBlockCount(UCHAR DriveNumber)
Definition: uefidisk.c:1563
UCHAR FrldrBootDrive
Definition: uefidisk.c:104
static BOOLEAN UefiSetBootpath(VOID)
Definition: uefidisk.c:1191
ULONG FrldrBootPartition
Definition: uefidisk.c:105
struct _INTERNAL_UEFI_DISK * PINTERNAL_UEFI_DISK
#define FIRST_PARTITION
Definition: uefidisk.c:18
#define ALIGN_UP_POINTER_BY(ptr, align)
Definition: umtypes.h:85
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_In_ ULONG SectorSize
Definition: halfuncs.h:291
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175