Как я писал ранее, схема разделов Apple Partition Map не приспособлена к использованию на больших дисках - из-за 32-битных счётчиков максимальный размер диска при размере блока 512 байт может быть лишь 2 TB.

Apple серьёзно прорабатывала возможность адаптации Apple Partition Map для поддержки больших дисков, однако требуемые изменения привели бы к неработоспособности всех инструментов, работающих с разделами, поэтому было принято разумное решение переключиться на принципиально новую схему. После серьёзных размышлений Apple решила использовать GPT.

Схема разделов GUID partition table (GPT) была представлена Intel как часть реализации комплексной задачи по переходу на современное firmware для Intel-совместимых компьютеров. Традиционно на них было установлено firmware BIOS, использующее схему разделов Master Boot Record (MBR). Схема MBR имела большое количество ограничений, не позволяющих использовать её на современных компьютерах. Для преодоления этих ограничений компания Intel разработала современное firmware Extensible Firmware Interface (EFI), включающее в себя новую схему разделов GPT.

Одним из больших преимуществ схемы GPT было то, что она была закреплена в формальных стандартах (документы доступны для списывания):

В статье я использую такие источники:

Вопрос о GPT не помещается в одну статью, поэтому я разобью его на три части:

  1. Protective MBR
  2. Partition Table Header
  3. Partition Entry Array

Обзор GPT

GPT простая, но эффективная схема разделов. Общая схема использования блоков показана в таблице (n - количество блоков на диске, b - количество блоков, использующихся для описания массива с записями о разделах, обычно 32):

Меня лично восхитил блок 0 "Protective MBR" - это отличная "защита от дурака". В нём в формате MBR вся область, используемая под схему разделов GPT и разделы GPT определены, как один раздел. Таким образом программы работы с разделами, ничего не знающие о GPT, не смогут случайно ничего изменить (конечно же, от намеренного изменения никто защитить не сможет). Такие программы видят диск GPT, как диск MBR с одним разделом неизвестного типа (0xEE).

GPT использует логическую адресацию блоков на диске Logical Block Addressing (LBA) в отличие от старой адресации Cylinder-Head-Sector (CHS). Размер блока обычно 512 байт, но он может быть и другим. Штатных утилит для просмотра размера блока я не нашёл, поэтому использую программу из книги "Mac OS X Internals" - для моего диска он действительно 512 байт.

В графическом виде GPT выглядит так (128 разделов - столько зарезервировано в Windows 2003 Server, насчёт Mac OS X посмотрим дальше):

Для экспериментов будем использовать USB-диск со схемой разделов GPT и двумя разделами:

LBA 0. Protective MBR

Формат MBR описан в таблице (из Unified Extensible Firmware Interface Specification):

Mnemonic Byte Length Description
BootCode 0 440 Code used on a legacy system to select a partition record and load the first block (sector) of the partition pointed to by the partition record. This code is not executed on UEFI systems.
UniqueMBRSignature 440 4 Unique Disk Signature, this is an optional feature and not on all hard drives. This value is always written by the OS and is never written by EFI firmware.
Unknown 444 2 Unknown
PartitionRecord 446 16*4 Array of four legacy MBR partition records (смотри следующую таблицу).
Signature 510 2 Must be 0xaa55 (i.e., byte 510 contains 0x55 and byte 511 contains 0xaa).
Reserved 512 BlockSize - 512 The rest of the logical block, if any, is reserved.

PartitionRecord описан в следующей таблице. В описании указан общий формат, а после пометки GPT то, что должно быть для Protective MBR.

Mnemonic Byte Length Description
BootIndicator 0 1 Not used by EFI firmware. 0x80 indicates that this is the bootable legacy partition. (GPT) Must be set to zero to indicate nonbootable partition.
StartingCHS 1 3 Start of partition in CHS address format, not used by EFI firmware. (GPT) Must be 0x000200, corresponding to the StartingLBA.
OSType 4 1 Type of partition. 0xEF defines an EFI system partition. 0xEE is used by a protective MBR (Table 12) to define a fake partition covering the entire disk. Other values are used by legacy operating systems, and are allocated independently of the UEFI specification. (GPT) Must be 0xEE.
EndingCHS 5 3 End of partition in CHS address format, not used by EFI firmware. (GPT) Set to the CHS address of the last logical block on the disk. Must be set to 0xFFFFFF if it is not possible to represent the value in these fields.
StartingLBA 8 4 Starting LBA of the partition on the disk. Used by EFI firmware to define the start of the partition. (GPT) Must be 0x00000001.
SizeInLBA 12 4 Size of the partition in LBA units of logical blocks. Used by EFI firmware to determine the size of the partition. (GPT) Size of the disk minus one. Set to 0xFFFFFFFF if the size of the disk is too large to be represented in this field.

Первый (нулевой) блок содержит такие данные:

$ sudo dd if=/dev/disk4 of=/dev/stdout bs=512 count=1 skip=0 2>/dev/null | hexdump -C
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 fe  |................|
000001c0  ff ff ee fe ff ff 01 00  00 00 af ea 42 25 00 00  |............B%..|
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200
    MBR:
  • 0000 440 bytes. BootCode. Все нули.
  • 01B8 4 bytes. UniqueMBRSignature. 00 00 00 00.
  • 01BC 2 bytes. Unknown. 00 00.
  • 01BE 64 bytes. PartitionRecord (4 x 16-ти байтовых записей в формате IBM Partition Table). 00 fe ff ff ee fe ff ff 01 00 00 00 af ea 42 25
  • 01FE 2 bytes. MBR signature (0xAA55). 55 AA - в обратной нотации (так уж повелось).
  • Если размер блока больше 512 байт, то остальное - Reserved. Для нашего случая блок - 512
    Рассмотрим информацию о разделе (00 fe ff ff ee fe ff ff 01 00 00 00 af ea 42 25)
  • 0x00 1 byte. BootIndicator (0x80 = bootable/active, 0x00 = non-bootable, other = invalid). 00 - non-bootable.
  • 0x01 3 bytes. StartingCHS. fe ff ff. Это древняя жуть, не будем искать разгадку - кто знает, куда нас заведёт это знание? Хорошо, что в EFI это не используется.
  • 0x04 1 byte. OSType. Есть хороший ресурс со всеми типами разделов. 0xEE = Indication that this legacy MBR is followed by an EFI header.
  • 0x05 3 bytes. EndingCHS. fe ff ff. Аналогично.
  • 0x08 4 bytes. StartingLBA. 01 00 00 00 в обратной нотации читается как 00 00 00 01. Вспоминаем таблицу - "Must be 0x00000001".
  • 0x0C 4 bytes. SizeInLBA in little-endian format. af ea 42 25 = 0x2542eaaf = 625142447 блоков

Для проверки количества блоков посмотрим информацию по диску:

$ diskutil info disk4 | grep "Total Size"
   Total Size:               320.1 GB (320072933376 Bytes) (exactly 625142448 512-Byte-Blocks)

Количество блоков в разделе 625142447, один блок - MBR, что даёт требуемое количество блоков на диске 625142448. В итоге программы, знающие только об MBR будут действительно видеть диск MBR с одним разделом типа 0xEE.

To be continued...

В следующей части разберём "Partition Table Header".