master
   1const std = @import("../../std.zig");
   2const assert = std.debug.assert;
   3const uefi = std.os.uefi;
   4const Guid = uefi.Guid;
   5
   6pub const DevicePath = union(Type) {
   7    hardware: Hardware,
   8    acpi: Acpi,
   9    messaging: Messaging,
  10    media: Media,
  11    bios_boot_specification: BiosBootSpecification,
  12    end: End,
  13
  14    pub const Type = enum(u8) {
  15        hardware = 0x01,
  16        acpi = 0x02,
  17        messaging = 0x03,
  18        media = 0x04,
  19        bios_boot_specification = 0x05,
  20        end = 0x7f,
  21        _,
  22    };
  23
  24    pub const Hardware = union(Subtype) {
  25        pci: *const PciDevicePath,
  26        pc_card: *const PcCardDevicePath,
  27        memory_mapped: *const MemoryMappedDevicePath,
  28        vendor: *const VendorDevicePath,
  29        controller: *const ControllerDevicePath,
  30        bmc: *const BmcDevicePath,
  31
  32        pub const Subtype = enum(u8) {
  33            pci = 1,
  34            pc_card = 2,
  35            memory_mapped = 3,
  36            vendor = 4,
  37            controller = 5,
  38            bmc = 6,
  39            _,
  40        };
  41
  42        pub const PciDevicePath = extern struct {
  43            type: DevicePath.Type,
  44            subtype: Subtype,
  45            length: u16 align(1),
  46            function: u8,
  47            device: u8,
  48        };
  49
  50        comptime {
  51            assert(6 == @sizeOf(PciDevicePath));
  52            assert(1 == @alignOf(PciDevicePath));
  53
  54            assert(0 == @offsetOf(PciDevicePath, "type"));
  55            assert(1 == @offsetOf(PciDevicePath, "subtype"));
  56            assert(2 == @offsetOf(PciDevicePath, "length"));
  57            assert(4 == @offsetOf(PciDevicePath, "function"));
  58            assert(5 == @offsetOf(PciDevicePath, "device"));
  59        }
  60
  61        pub const PcCardDevicePath = extern struct {
  62            type: DevicePath.Type,
  63            subtype: Subtype,
  64            length: u16 align(1),
  65            function_number: u8,
  66        };
  67
  68        comptime {
  69            assert(5 == @sizeOf(PcCardDevicePath));
  70            assert(1 == @alignOf(PcCardDevicePath));
  71
  72            assert(0 == @offsetOf(PcCardDevicePath, "type"));
  73            assert(1 == @offsetOf(PcCardDevicePath, "subtype"));
  74            assert(2 == @offsetOf(PcCardDevicePath, "length"));
  75            assert(4 == @offsetOf(PcCardDevicePath, "function_number"));
  76        }
  77
  78        pub const MemoryMappedDevicePath = extern struct {
  79            type: DevicePath.Type,
  80            subtype: Subtype,
  81            length: u16 align(1),
  82            memory_type: u32 align(1),
  83            start_address: u64 align(1),
  84            end_address: u64 align(1),
  85        };
  86
  87        comptime {
  88            assert(24 == @sizeOf(MemoryMappedDevicePath));
  89            assert(1 == @alignOf(MemoryMappedDevicePath));
  90
  91            assert(0 == @offsetOf(MemoryMappedDevicePath, "type"));
  92            assert(1 == @offsetOf(MemoryMappedDevicePath, "subtype"));
  93            assert(2 == @offsetOf(MemoryMappedDevicePath, "length"));
  94            assert(4 == @offsetOf(MemoryMappedDevicePath, "memory_type"));
  95            assert(8 == @offsetOf(MemoryMappedDevicePath, "start_address"));
  96            assert(16 == @offsetOf(MemoryMappedDevicePath, "end_address"));
  97        }
  98
  99        pub const VendorDevicePath = extern struct {
 100            type: DevicePath.Type,
 101            subtype: Subtype,
 102            length: u16 align(1),
 103            vendor_guid: Guid align(1),
 104        };
 105
 106        comptime {
 107            assert(20 == @sizeOf(VendorDevicePath));
 108            assert(1 == @alignOf(VendorDevicePath));
 109
 110            assert(0 == @offsetOf(VendorDevicePath, "type"));
 111            assert(1 == @offsetOf(VendorDevicePath, "subtype"));
 112            assert(2 == @offsetOf(VendorDevicePath, "length"));
 113            assert(4 == @offsetOf(VendorDevicePath, "vendor_guid"));
 114        }
 115
 116        pub const ControllerDevicePath = extern struct {
 117            type: DevicePath.Type,
 118            subtype: Subtype,
 119            length: u16 align(1),
 120            controller_number: u32 align(1),
 121        };
 122
 123        comptime {
 124            assert(8 == @sizeOf(ControllerDevicePath));
 125            assert(1 == @alignOf(ControllerDevicePath));
 126
 127            assert(0 == @offsetOf(ControllerDevicePath, "type"));
 128            assert(1 == @offsetOf(ControllerDevicePath, "subtype"));
 129            assert(2 == @offsetOf(ControllerDevicePath, "length"));
 130            assert(4 == @offsetOf(ControllerDevicePath, "controller_number"));
 131        }
 132
 133        pub const BmcDevicePath = extern struct {
 134            type: DevicePath.Type,
 135            subtype: Subtype,
 136            length: u16 align(1),
 137            interface_type: u8,
 138            base_address: u64 align(1),
 139        };
 140
 141        comptime {
 142            assert(13 == @sizeOf(BmcDevicePath));
 143            assert(1 == @alignOf(BmcDevicePath));
 144
 145            assert(0 == @offsetOf(BmcDevicePath, "type"));
 146            assert(1 == @offsetOf(BmcDevicePath, "subtype"));
 147            assert(2 == @offsetOf(BmcDevicePath, "length"));
 148            assert(4 == @offsetOf(BmcDevicePath, "interface_type"));
 149            assert(5 == @offsetOf(BmcDevicePath, "base_address"));
 150        }
 151    };
 152
 153    pub const Acpi = union(Subtype) {
 154        acpi: *const BaseAcpiDevicePath,
 155        expanded_acpi: *const ExpandedAcpiDevicePath,
 156        adr: *const AdrDevicePath,
 157
 158        pub const Subtype = enum(u8) {
 159            acpi = 1,
 160            expanded_acpi = 2,
 161            adr = 3,
 162            _,
 163        };
 164
 165        pub const BaseAcpiDevicePath = extern struct {
 166            type: DevicePath.Type,
 167            subtype: Subtype,
 168            length: u16 align(1),
 169            hid: u32 align(1),
 170            uid: u32 align(1),
 171        };
 172
 173        comptime {
 174            assert(12 == @sizeOf(BaseAcpiDevicePath));
 175            assert(1 == @alignOf(BaseAcpiDevicePath));
 176
 177            assert(0 == @offsetOf(BaseAcpiDevicePath, "type"));
 178            assert(1 == @offsetOf(BaseAcpiDevicePath, "subtype"));
 179            assert(2 == @offsetOf(BaseAcpiDevicePath, "length"));
 180            assert(4 == @offsetOf(BaseAcpiDevicePath, "hid"));
 181            assert(8 == @offsetOf(BaseAcpiDevicePath, "uid"));
 182        }
 183
 184        pub const ExpandedAcpiDevicePath = extern struct {
 185            type: DevicePath.Type,
 186            subtype: Subtype,
 187            length: u16 align(1),
 188            hid: u32 align(1),
 189            uid: u32 align(1),
 190            cid: u32 align(1),
 191            // variable length u16[*:0] strings
 192            // hid_str, uid_str, cid_str
 193        };
 194
 195        comptime {
 196            assert(16 == @sizeOf(ExpandedAcpiDevicePath));
 197            assert(1 == @alignOf(ExpandedAcpiDevicePath));
 198
 199            assert(0 == @offsetOf(ExpandedAcpiDevicePath, "type"));
 200            assert(1 == @offsetOf(ExpandedAcpiDevicePath, "subtype"));
 201            assert(2 == @offsetOf(ExpandedAcpiDevicePath, "length"));
 202            assert(4 == @offsetOf(ExpandedAcpiDevicePath, "hid"));
 203            assert(8 == @offsetOf(ExpandedAcpiDevicePath, "uid"));
 204            assert(12 == @offsetOf(ExpandedAcpiDevicePath, "cid"));
 205        }
 206
 207        pub const AdrDevicePath = extern struct {
 208            type: DevicePath.Type,
 209            subtype: Subtype,
 210            length: u16 align(1),
 211            adr: u32 align(1),
 212
 213            // multiple adr entries can optionally follow
 214            pub fn adrs(self: *const AdrDevicePath) []align(1) const u32 {
 215                // self.length is a minimum of 8 with one adr which is size 4.
 216                const entries = (self.length - 4) / @sizeOf(u32);
 217                return @as([*]align(1) const u32, @ptrCast(&self.adr))[0..entries];
 218            }
 219        };
 220
 221        comptime {
 222            assert(8 == @sizeOf(AdrDevicePath));
 223            assert(1 == @alignOf(AdrDevicePath));
 224
 225            assert(0 == @offsetOf(AdrDevicePath, "type"));
 226            assert(1 == @offsetOf(AdrDevicePath, "subtype"));
 227            assert(2 == @offsetOf(AdrDevicePath, "length"));
 228            assert(4 == @offsetOf(AdrDevicePath, "adr"));
 229        }
 230    };
 231
 232    pub const Messaging = union(Subtype) {
 233        atapi: *const AtapiDevicePath,
 234        scsi: *const ScsiDevicePath,
 235        fibre_channel: *const FibreChannelDevicePath,
 236        fibre_channel_ex: *const FibreChannelExDevicePath,
 237        @"1394": *const F1394DevicePath,
 238        usb: *const UsbDevicePath,
 239        sata: *const SataDevicePath,
 240        usb_wwid: *const UsbWwidDevicePath,
 241        lun: *const DeviceLogicalUnitDevicePath,
 242        usb_class: *const UsbClassDevicePath,
 243        i2o: *const I2oDevicePath,
 244        mac_address: *const MacAddressDevicePath,
 245        ipv4: *const Ipv4DevicePath,
 246        ipv6: *const Ipv6DevicePath,
 247        vlan: *const VlanDevicePath,
 248        infini_band: *const InfiniBandDevicePath,
 249        uart: *const UartDevicePath,
 250        vendor: *const VendorDefinedDevicePath,
 251
 252        pub const Subtype = enum(u8) {
 253            atapi = 1,
 254            scsi = 2,
 255            fibre_channel = 3,
 256            fibre_channel_ex = 21,
 257            @"1394" = 4,
 258            usb = 5,
 259            sata = 18,
 260            usb_wwid = 16,
 261            lun = 17,
 262            usb_class = 15,
 263            i2o = 6,
 264            mac_address = 11,
 265            ipv4 = 12,
 266            ipv6 = 13,
 267            vlan = 20,
 268            infini_band = 9,
 269            uart = 14,
 270            vendor = 10,
 271            _,
 272        };
 273
 274        pub const AtapiDevicePath = extern struct {
 275            pub const Role = enum(u8) {
 276                master = 0,
 277                slave = 1,
 278            };
 279
 280            pub const Rank = enum(u8) {
 281                primary = 0,
 282                secondary = 1,
 283            };
 284
 285            type: DevicePath.Type,
 286            subtype: Subtype,
 287            length: u16 align(1),
 288            primary_secondary: Rank,
 289            slave_master: Role,
 290            logical_unit_number: u16 align(1),
 291        };
 292
 293        comptime {
 294            assert(8 == @sizeOf(AtapiDevicePath));
 295            assert(1 == @alignOf(AtapiDevicePath));
 296
 297            assert(0 == @offsetOf(AtapiDevicePath, "type"));
 298            assert(1 == @offsetOf(AtapiDevicePath, "subtype"));
 299            assert(2 == @offsetOf(AtapiDevicePath, "length"));
 300            assert(4 == @offsetOf(AtapiDevicePath, "primary_secondary"));
 301            assert(5 == @offsetOf(AtapiDevicePath, "slave_master"));
 302            assert(6 == @offsetOf(AtapiDevicePath, "logical_unit_number"));
 303        }
 304
 305        pub const ScsiDevicePath = extern struct {
 306            type: DevicePath.Type,
 307            subtype: Subtype,
 308            length: u16 align(1),
 309            target_id: u16 align(1),
 310            logical_unit_number: u16 align(1),
 311        };
 312
 313        comptime {
 314            assert(8 == @sizeOf(ScsiDevicePath));
 315            assert(1 == @alignOf(ScsiDevicePath));
 316
 317            assert(0 == @offsetOf(ScsiDevicePath, "type"));
 318            assert(1 == @offsetOf(ScsiDevicePath, "subtype"));
 319            assert(2 == @offsetOf(ScsiDevicePath, "length"));
 320            assert(4 == @offsetOf(ScsiDevicePath, "target_id"));
 321            assert(6 == @offsetOf(ScsiDevicePath, "logical_unit_number"));
 322        }
 323
 324        pub const FibreChannelDevicePath = extern struct {
 325            type: DevicePath.Type,
 326            subtype: Subtype,
 327            length: u16 align(1),
 328            reserved: u32 align(1),
 329            world_wide_name: u64 align(1),
 330            logical_unit_number: u64 align(1),
 331        };
 332
 333        comptime {
 334            assert(24 == @sizeOf(FibreChannelDevicePath));
 335            assert(1 == @alignOf(FibreChannelDevicePath));
 336
 337            assert(0 == @offsetOf(FibreChannelDevicePath, "type"));
 338            assert(1 == @offsetOf(FibreChannelDevicePath, "subtype"));
 339            assert(2 == @offsetOf(FibreChannelDevicePath, "length"));
 340            assert(4 == @offsetOf(FibreChannelDevicePath, "reserved"));
 341            assert(8 == @offsetOf(FibreChannelDevicePath, "world_wide_name"));
 342            assert(16 == @offsetOf(FibreChannelDevicePath, "logical_unit_number"));
 343        }
 344
 345        pub const FibreChannelExDevicePath = extern struct {
 346            type: DevicePath.Type,
 347            subtype: Subtype,
 348            length: u16 align(1),
 349            reserved: u32 align(1),
 350            world_wide_name: u64 align(1),
 351            logical_unit_number: u64 align(1),
 352        };
 353
 354        comptime {
 355            assert(24 == @sizeOf(FibreChannelExDevicePath));
 356            assert(1 == @alignOf(FibreChannelExDevicePath));
 357
 358            assert(0 == @offsetOf(FibreChannelExDevicePath, "type"));
 359            assert(1 == @offsetOf(FibreChannelExDevicePath, "subtype"));
 360            assert(2 == @offsetOf(FibreChannelExDevicePath, "length"));
 361            assert(4 == @offsetOf(FibreChannelExDevicePath, "reserved"));
 362            assert(8 == @offsetOf(FibreChannelExDevicePath, "world_wide_name"));
 363            assert(16 == @offsetOf(FibreChannelExDevicePath, "logical_unit_number"));
 364        }
 365
 366        pub const F1394DevicePath = extern struct {
 367            type: DevicePath.Type,
 368            subtype: Subtype,
 369            length: u16 align(1),
 370            reserved: u32 align(1),
 371            guid: u64 align(1),
 372        };
 373
 374        comptime {
 375            assert(16 == @sizeOf(F1394DevicePath));
 376            assert(1 == @alignOf(F1394DevicePath));
 377
 378            assert(0 == @offsetOf(F1394DevicePath, "type"));
 379            assert(1 == @offsetOf(F1394DevicePath, "subtype"));
 380            assert(2 == @offsetOf(F1394DevicePath, "length"));
 381            assert(4 == @offsetOf(F1394DevicePath, "reserved"));
 382            assert(8 == @offsetOf(F1394DevicePath, "guid"));
 383        }
 384
 385        pub const UsbDevicePath = extern struct {
 386            type: DevicePath.Type,
 387            subtype: Subtype,
 388            length: u16 align(1),
 389            parent_port_number: u8,
 390            interface_number: u8,
 391        };
 392
 393        comptime {
 394            assert(6 == @sizeOf(UsbDevicePath));
 395            assert(1 == @alignOf(UsbDevicePath));
 396
 397            assert(0 == @offsetOf(UsbDevicePath, "type"));
 398            assert(1 == @offsetOf(UsbDevicePath, "subtype"));
 399            assert(2 == @offsetOf(UsbDevicePath, "length"));
 400            assert(4 == @offsetOf(UsbDevicePath, "parent_port_number"));
 401            assert(5 == @offsetOf(UsbDevicePath, "interface_number"));
 402        }
 403
 404        pub const SataDevicePath = extern struct {
 405            type: DevicePath.Type,
 406            subtype: Subtype,
 407            length: u16 align(1),
 408            hba_port_number: u16 align(1),
 409            port_multiplier_port_number: u16 align(1),
 410            logical_unit_number: u16 align(1),
 411        };
 412
 413        comptime {
 414            assert(10 == @sizeOf(SataDevicePath));
 415            assert(1 == @alignOf(SataDevicePath));
 416
 417            assert(0 == @offsetOf(SataDevicePath, "type"));
 418            assert(1 == @offsetOf(SataDevicePath, "subtype"));
 419            assert(2 == @offsetOf(SataDevicePath, "length"));
 420            assert(4 == @offsetOf(SataDevicePath, "hba_port_number"));
 421            assert(6 == @offsetOf(SataDevicePath, "port_multiplier_port_number"));
 422            assert(8 == @offsetOf(SataDevicePath, "logical_unit_number"));
 423        }
 424
 425        pub const UsbWwidDevicePath = extern struct {
 426            type: DevicePath.Type,
 427            subtype: Subtype,
 428            length: u16 align(1),
 429            interface_number: u16 align(1),
 430            device_vendor_id: u16 align(1),
 431            device_product_id: u16 align(1),
 432
 433            pub fn serial_number(self: *const UsbWwidDevicePath) []align(1) const u16 {
 434                const serial_len = (self.length - @sizeOf(UsbWwidDevicePath)) / @sizeOf(u16);
 435                return @as([*]align(1) const u16, @ptrCast(@as([*]const u8, @ptrCast(self)) + @sizeOf(UsbWwidDevicePath)))[0..serial_len];
 436            }
 437        };
 438
 439        comptime {
 440            assert(10 == @sizeOf(UsbWwidDevicePath));
 441            assert(1 == @alignOf(UsbWwidDevicePath));
 442
 443            assert(0 == @offsetOf(UsbWwidDevicePath, "type"));
 444            assert(1 == @offsetOf(UsbWwidDevicePath, "subtype"));
 445            assert(2 == @offsetOf(UsbWwidDevicePath, "length"));
 446            assert(4 == @offsetOf(UsbWwidDevicePath, "interface_number"));
 447            assert(6 == @offsetOf(UsbWwidDevicePath, "device_vendor_id"));
 448            assert(8 == @offsetOf(UsbWwidDevicePath, "device_product_id"));
 449        }
 450
 451        pub const DeviceLogicalUnitDevicePath = extern struct {
 452            type: DevicePath.Type,
 453            subtype: Subtype,
 454            length: u16 align(1),
 455            lun: u8,
 456        };
 457
 458        comptime {
 459            assert(5 == @sizeOf(DeviceLogicalUnitDevicePath));
 460            assert(1 == @alignOf(DeviceLogicalUnitDevicePath));
 461
 462            assert(0 == @offsetOf(DeviceLogicalUnitDevicePath, "type"));
 463            assert(1 == @offsetOf(DeviceLogicalUnitDevicePath, "subtype"));
 464            assert(2 == @offsetOf(DeviceLogicalUnitDevicePath, "length"));
 465            assert(4 == @offsetOf(DeviceLogicalUnitDevicePath, "lun"));
 466        }
 467
 468        pub const UsbClassDevicePath = extern struct {
 469            type: DevicePath.Type,
 470            subtype: Subtype,
 471            length: u16 align(1),
 472            vendor_id: u16 align(1),
 473            product_id: u16 align(1),
 474            device_class: u8,
 475            device_subclass: u8,
 476            device_protocol: u8,
 477        };
 478
 479        comptime {
 480            assert(11 == @sizeOf(UsbClassDevicePath));
 481            assert(1 == @alignOf(UsbClassDevicePath));
 482
 483            assert(0 == @offsetOf(UsbClassDevicePath, "type"));
 484            assert(1 == @offsetOf(UsbClassDevicePath, "subtype"));
 485            assert(2 == @offsetOf(UsbClassDevicePath, "length"));
 486            assert(4 == @offsetOf(UsbClassDevicePath, "vendor_id"));
 487            assert(6 == @offsetOf(UsbClassDevicePath, "product_id"));
 488            assert(8 == @offsetOf(UsbClassDevicePath, "device_class"));
 489            assert(9 == @offsetOf(UsbClassDevicePath, "device_subclass"));
 490            assert(10 == @offsetOf(UsbClassDevicePath, "device_protocol"));
 491        }
 492
 493        pub const I2oDevicePath = extern struct {
 494            type: DevicePath.Type,
 495            subtype: Subtype,
 496            length: u16 align(1),
 497            tid: u32 align(1),
 498        };
 499
 500        comptime {
 501            assert(8 == @sizeOf(I2oDevicePath));
 502            assert(1 == @alignOf(I2oDevicePath));
 503
 504            assert(0 == @offsetOf(I2oDevicePath, "type"));
 505            assert(1 == @offsetOf(I2oDevicePath, "subtype"));
 506            assert(2 == @offsetOf(I2oDevicePath, "length"));
 507            assert(4 == @offsetOf(I2oDevicePath, "tid"));
 508        }
 509
 510        pub const MacAddressDevicePath = extern struct {
 511            type: DevicePath.Type,
 512            subtype: Subtype,
 513            length: u16 align(1),
 514            mac_address: uefi.MacAddress,
 515            if_type: u8,
 516        };
 517
 518        comptime {
 519            assert(37 == @sizeOf(MacAddressDevicePath));
 520            assert(1 == @alignOf(MacAddressDevicePath));
 521
 522            assert(0 == @offsetOf(MacAddressDevicePath, "type"));
 523            assert(1 == @offsetOf(MacAddressDevicePath, "subtype"));
 524            assert(2 == @offsetOf(MacAddressDevicePath, "length"));
 525            assert(4 == @offsetOf(MacAddressDevicePath, "mac_address"));
 526            assert(36 == @offsetOf(MacAddressDevicePath, "if_type"));
 527        }
 528
 529        pub const Ipv4DevicePath = extern struct {
 530            pub const IpType = enum(u8) {
 531                dhcp = 0,
 532                static = 1,
 533            };
 534
 535            type: DevicePath.Type,
 536            subtype: Subtype,
 537            length: u16 align(1),
 538            local_ip_address: uefi.Ipv4Address align(1),
 539            remote_ip_address: uefi.Ipv4Address align(1),
 540            local_port: u16 align(1),
 541            remote_port: u16 align(1),
 542            network_protocol: u16 align(1),
 543            static_ip_address: IpType,
 544            gateway_ip_address: u32 align(1),
 545            subnet_mask: u32 align(1),
 546        };
 547
 548        comptime {
 549            assert(27 == @sizeOf(Ipv4DevicePath));
 550            assert(1 == @alignOf(Ipv4DevicePath));
 551
 552            assert(0 == @offsetOf(Ipv4DevicePath, "type"));
 553            assert(1 == @offsetOf(Ipv4DevicePath, "subtype"));
 554            assert(2 == @offsetOf(Ipv4DevicePath, "length"));
 555            assert(4 == @offsetOf(Ipv4DevicePath, "local_ip_address"));
 556            assert(8 == @offsetOf(Ipv4DevicePath, "remote_ip_address"));
 557            assert(12 == @offsetOf(Ipv4DevicePath, "local_port"));
 558            assert(14 == @offsetOf(Ipv4DevicePath, "remote_port"));
 559            assert(16 == @offsetOf(Ipv4DevicePath, "network_protocol"));
 560            assert(18 == @offsetOf(Ipv4DevicePath, "static_ip_address"));
 561            assert(19 == @offsetOf(Ipv4DevicePath, "gateway_ip_address"));
 562            assert(23 == @offsetOf(Ipv4DevicePath, "subnet_mask"));
 563        }
 564
 565        pub const Ipv6DevicePath = extern struct {
 566            pub const Origin = enum(u8) {
 567                manual = 0,
 568                assigned_stateless = 1,
 569                assigned_stateful = 2,
 570            };
 571
 572            type: DevicePath.Type,
 573            subtype: Subtype,
 574            length: u16 align(1),
 575            local_ip_address: uefi.Ipv6Address,
 576            remote_ip_address: uefi.Ipv6Address,
 577            local_port: u16 align(1),
 578            remote_port: u16 align(1),
 579            protocol: u16 align(1),
 580            ip_address_origin: Origin,
 581            prefix_length: u8,
 582            gateway_ip_address: uefi.Ipv6Address,
 583        };
 584
 585        comptime {
 586            assert(60 == @sizeOf(Ipv6DevicePath));
 587            assert(1 == @alignOf(Ipv6DevicePath));
 588
 589            assert(0 == @offsetOf(Ipv6DevicePath, "type"));
 590            assert(1 == @offsetOf(Ipv6DevicePath, "subtype"));
 591            assert(2 == @offsetOf(Ipv6DevicePath, "length"));
 592            assert(4 == @offsetOf(Ipv6DevicePath, "local_ip_address"));
 593            assert(20 == @offsetOf(Ipv6DevicePath, "remote_ip_address"));
 594            assert(36 == @offsetOf(Ipv6DevicePath, "local_port"));
 595            assert(38 == @offsetOf(Ipv6DevicePath, "remote_port"));
 596            assert(40 == @offsetOf(Ipv6DevicePath, "protocol"));
 597            assert(42 == @offsetOf(Ipv6DevicePath, "ip_address_origin"));
 598            assert(43 == @offsetOf(Ipv6DevicePath, "prefix_length"));
 599            assert(44 == @offsetOf(Ipv6DevicePath, "gateway_ip_address"));
 600        }
 601
 602        pub const VlanDevicePath = extern struct {
 603            type: DevicePath.Type,
 604            subtype: Subtype,
 605            length: u16 align(1),
 606            vlan_id: u16 align(1),
 607        };
 608
 609        comptime {
 610            assert(6 == @sizeOf(VlanDevicePath));
 611            assert(1 == @alignOf(VlanDevicePath));
 612
 613            assert(0 == @offsetOf(VlanDevicePath, "type"));
 614            assert(1 == @offsetOf(VlanDevicePath, "subtype"));
 615            assert(2 == @offsetOf(VlanDevicePath, "length"));
 616            assert(4 == @offsetOf(VlanDevicePath, "vlan_id"));
 617        }
 618
 619        pub const InfiniBandDevicePath = extern struct {
 620            pub const ResourceFlags = packed struct(u32) {
 621                pub const ControllerType = enum(u1) {
 622                    ioc = 0,
 623                    service = 1,
 624                };
 625
 626                ioc_or_service: ControllerType,
 627                extend_boot_environment: bool,
 628                console_protocol: bool,
 629                storage_protocol: bool,
 630                network_protocol: bool,
 631
 632                // u1 + 4 * bool = 5 bits, we need a total of 32 bits
 633                reserved: u27,
 634            };
 635
 636            type: DevicePath.Type,
 637            subtype: Subtype,
 638            length: u16 align(1),
 639            resource_flags: ResourceFlags align(1),
 640            port_gid: [16]u8,
 641            service_id: u64 align(1),
 642            target_port_id: u64 align(1),
 643            device_id: u64 align(1),
 644        };
 645
 646        comptime {
 647            assert(48 == @sizeOf(InfiniBandDevicePath));
 648            assert(1 == @alignOf(InfiniBandDevicePath));
 649
 650            assert(0 == @offsetOf(InfiniBandDevicePath, "type"));
 651            assert(1 == @offsetOf(InfiniBandDevicePath, "subtype"));
 652            assert(2 == @offsetOf(InfiniBandDevicePath, "length"));
 653            assert(4 == @offsetOf(InfiniBandDevicePath, "resource_flags"));
 654            assert(8 == @offsetOf(InfiniBandDevicePath, "port_gid"));
 655            assert(24 == @offsetOf(InfiniBandDevicePath, "service_id"));
 656            assert(32 == @offsetOf(InfiniBandDevicePath, "target_port_id"));
 657            assert(40 == @offsetOf(InfiniBandDevicePath, "device_id"));
 658        }
 659
 660        pub const UartDevicePath = extern struct {
 661            pub const Parity = enum(u8) {
 662                default = 0,
 663                none = 1,
 664                even = 2,
 665                odd = 3,
 666                mark = 4,
 667                space = 5,
 668                _,
 669            };
 670
 671            pub const StopBits = enum(u8) {
 672                default = 0,
 673                one = 1,
 674                one_and_a_half = 2,
 675                two = 3,
 676                _,
 677            };
 678
 679            type: DevicePath.Type,
 680            subtype: Subtype,
 681            length: u16 align(1),
 682            reserved: u32 align(1),
 683            baud_rate: u64 align(1),
 684            data_bits: u8,
 685            parity: Parity,
 686            stop_bits: StopBits,
 687        };
 688
 689        comptime {
 690            assert(19 == @sizeOf(UartDevicePath));
 691            assert(1 == @alignOf(UartDevicePath));
 692
 693            assert(0 == @offsetOf(UartDevicePath, "type"));
 694            assert(1 == @offsetOf(UartDevicePath, "subtype"));
 695            assert(2 == @offsetOf(UartDevicePath, "length"));
 696            assert(4 == @offsetOf(UartDevicePath, "reserved"));
 697            assert(8 == @offsetOf(UartDevicePath, "baud_rate"));
 698            assert(16 == @offsetOf(UartDevicePath, "data_bits"));
 699            assert(17 == @offsetOf(UartDevicePath, "parity"));
 700            assert(18 == @offsetOf(UartDevicePath, "stop_bits"));
 701        }
 702
 703        pub const VendorDefinedDevicePath = extern struct {
 704            type: DevicePath.Type,
 705            subtype: Subtype,
 706            length: u16 align(1),
 707            vendor_guid: Guid align(1),
 708        };
 709
 710        comptime {
 711            assert(20 == @sizeOf(VendorDefinedDevicePath));
 712            assert(1 == @alignOf(VendorDefinedDevicePath));
 713
 714            assert(0 == @offsetOf(VendorDefinedDevicePath, "type"));
 715            assert(1 == @offsetOf(VendorDefinedDevicePath, "subtype"));
 716            assert(2 == @offsetOf(VendorDefinedDevicePath, "length"));
 717            assert(4 == @offsetOf(VendorDefinedDevicePath, "vendor_guid"));
 718        }
 719    };
 720
 721    pub const Media = union(Subtype) {
 722        hard_drive: *const HardDriveDevicePath,
 723        cdrom: *const CdromDevicePath,
 724        vendor: *const VendorDevicePath,
 725        file_path: *const FilePathDevicePath,
 726        media_protocol: *const MediaProtocolDevicePath,
 727        piwg_firmware_file: *const PiwgFirmwareFileDevicePath,
 728        piwg_firmware_volume: *const PiwgFirmwareVolumeDevicePath,
 729        relative_offset_range: *const RelativeOffsetRangeDevicePath,
 730        ram_disk: *const RamDiskDevicePath,
 731
 732        pub const Subtype = enum(u8) {
 733            hard_drive = 1,
 734            cdrom = 2,
 735            vendor = 3,
 736            file_path = 4,
 737            media_protocol = 5,
 738            piwg_firmware_file = 6,
 739            piwg_firmware_volume = 7,
 740            relative_offset_range = 8,
 741            ram_disk = 9,
 742            _,
 743        };
 744
 745        pub const HardDriveDevicePath = extern struct {
 746            pub const Format = enum(u8) {
 747                legacy_mbr = 0x01,
 748                guid_partition_table = 0x02,
 749            };
 750
 751            pub const SignatureType = enum(u8) {
 752                no_signature = 0x00,
 753                /// "32-bit signature from address 0x1b8 of the type 0x01 MBR"
 754                mbr_signature = 0x01,
 755                guid_signature = 0x02,
 756            };
 757
 758            type: DevicePath.Type,
 759            subtype: Subtype,
 760            length: u16 align(1),
 761            partition_number: u32 align(1),
 762            partition_start: u64 align(1),
 763            partition_size: u64 align(1),
 764            partition_signature: [16]u8,
 765            partition_format: Format,
 766            signature_type: SignatureType,
 767        };
 768
 769        comptime {
 770            assert(42 == @sizeOf(HardDriveDevicePath));
 771            assert(1 == @alignOf(HardDriveDevicePath));
 772
 773            assert(0 == @offsetOf(HardDriveDevicePath, "type"));
 774            assert(1 == @offsetOf(HardDriveDevicePath, "subtype"));
 775            assert(2 == @offsetOf(HardDriveDevicePath, "length"));
 776            assert(4 == @offsetOf(HardDriveDevicePath, "partition_number"));
 777            assert(8 == @offsetOf(HardDriveDevicePath, "partition_start"));
 778            assert(16 == @offsetOf(HardDriveDevicePath, "partition_size"));
 779            assert(24 == @offsetOf(HardDriveDevicePath, "partition_signature"));
 780            assert(40 == @offsetOf(HardDriveDevicePath, "partition_format"));
 781            assert(41 == @offsetOf(HardDriveDevicePath, "signature_type"));
 782        }
 783
 784        pub const CdromDevicePath = extern struct {
 785            type: DevicePath.Type,
 786            subtype: Subtype,
 787            length: u16 align(1),
 788            boot_entry: u32 align(1),
 789            partition_start: u64 align(1),
 790            partition_size: u64 align(1),
 791        };
 792
 793        comptime {
 794            assert(24 == @sizeOf(CdromDevicePath));
 795            assert(1 == @alignOf(CdromDevicePath));
 796
 797            assert(0 == @offsetOf(CdromDevicePath, "type"));
 798            assert(1 == @offsetOf(CdromDevicePath, "subtype"));
 799            assert(2 == @offsetOf(CdromDevicePath, "length"));
 800            assert(4 == @offsetOf(CdromDevicePath, "boot_entry"));
 801            assert(8 == @offsetOf(CdromDevicePath, "partition_start"));
 802            assert(16 == @offsetOf(CdromDevicePath, "partition_size"));
 803        }
 804
 805        pub const VendorDevicePath = extern struct {
 806            type: DevicePath.Type,
 807            subtype: Subtype,
 808            length: u16 align(1),
 809            guid: Guid align(1),
 810        };
 811
 812        comptime {
 813            assert(20 == @sizeOf(VendorDevicePath));
 814            assert(1 == @alignOf(VendorDevicePath));
 815
 816            assert(0 == @offsetOf(VendorDevicePath, "type"));
 817            assert(1 == @offsetOf(VendorDevicePath, "subtype"));
 818            assert(2 == @offsetOf(VendorDevicePath, "length"));
 819            assert(4 == @offsetOf(VendorDevicePath, "guid"));
 820        }
 821
 822        pub const FilePathDevicePath = extern struct {
 823            type: DevicePath.Type,
 824            subtype: Subtype,
 825            length: u16 align(1),
 826
 827            pub fn getPath(self: *const FilePathDevicePath) [*:0]align(1) const u16 {
 828                return @as([*:0]align(1) const u16, @ptrCast(@as([*]const u8, @ptrCast(self)) + @sizeOf(FilePathDevicePath)));
 829            }
 830        };
 831
 832        comptime {
 833            assert(4 == @sizeOf(FilePathDevicePath));
 834            assert(1 == @alignOf(FilePathDevicePath));
 835
 836            assert(0 == @offsetOf(FilePathDevicePath, "type"));
 837            assert(1 == @offsetOf(FilePathDevicePath, "subtype"));
 838            assert(2 == @offsetOf(FilePathDevicePath, "length"));
 839        }
 840
 841        pub const MediaProtocolDevicePath = extern struct {
 842            type: DevicePath.Type,
 843            subtype: Subtype,
 844            length: u16 align(1),
 845            guid: Guid align(1),
 846        };
 847
 848        comptime {
 849            assert(20 == @sizeOf(MediaProtocolDevicePath));
 850            assert(1 == @alignOf(MediaProtocolDevicePath));
 851
 852            assert(0 == @offsetOf(MediaProtocolDevicePath, "type"));
 853            assert(1 == @offsetOf(MediaProtocolDevicePath, "subtype"));
 854            assert(2 == @offsetOf(MediaProtocolDevicePath, "length"));
 855            assert(4 == @offsetOf(MediaProtocolDevicePath, "guid"));
 856        }
 857
 858        pub const PiwgFirmwareFileDevicePath = extern struct {
 859            type: DevicePath.Type,
 860            subtype: Subtype,
 861            length: u16 align(1),
 862            fv_filename: Guid align(1),
 863        };
 864
 865        comptime {
 866            assert(20 == @sizeOf(PiwgFirmwareFileDevicePath));
 867            assert(1 == @alignOf(PiwgFirmwareFileDevicePath));
 868
 869            assert(0 == @offsetOf(PiwgFirmwareFileDevicePath, "type"));
 870            assert(1 == @offsetOf(PiwgFirmwareFileDevicePath, "subtype"));
 871            assert(2 == @offsetOf(PiwgFirmwareFileDevicePath, "length"));
 872            assert(4 == @offsetOf(PiwgFirmwareFileDevicePath, "fv_filename"));
 873        }
 874
 875        pub const PiwgFirmwareVolumeDevicePath = extern struct {
 876            type: DevicePath.Type,
 877            subtype: Subtype,
 878            length: u16 align(1),
 879            fv_name: Guid align(1),
 880        };
 881
 882        comptime {
 883            assert(20 == @sizeOf(PiwgFirmwareVolumeDevicePath));
 884            assert(1 == @alignOf(PiwgFirmwareVolumeDevicePath));
 885
 886            assert(0 == @offsetOf(PiwgFirmwareVolumeDevicePath, "type"));
 887            assert(1 == @offsetOf(PiwgFirmwareVolumeDevicePath, "subtype"));
 888            assert(2 == @offsetOf(PiwgFirmwareVolumeDevicePath, "length"));
 889            assert(4 == @offsetOf(PiwgFirmwareVolumeDevicePath, "fv_name"));
 890        }
 891
 892        pub const RelativeOffsetRangeDevicePath = extern struct {
 893            type: DevicePath.Type,
 894            subtype: Subtype,
 895            length: u16 align(1),
 896            reserved: u32 align(1),
 897            start: u64 align(1),
 898            end: u64 align(1),
 899        };
 900
 901        comptime {
 902            assert(24 == @sizeOf(RelativeOffsetRangeDevicePath));
 903            assert(1 == @alignOf(RelativeOffsetRangeDevicePath));
 904
 905            assert(0 == @offsetOf(RelativeOffsetRangeDevicePath, "type"));
 906            assert(1 == @offsetOf(RelativeOffsetRangeDevicePath, "subtype"));
 907            assert(2 == @offsetOf(RelativeOffsetRangeDevicePath, "length"));
 908            assert(4 == @offsetOf(RelativeOffsetRangeDevicePath, "reserved"));
 909            assert(8 == @offsetOf(RelativeOffsetRangeDevicePath, "start"));
 910            assert(16 == @offsetOf(RelativeOffsetRangeDevicePath, "end"));
 911        }
 912
 913        pub const RamDiskDevicePath = extern struct {
 914            type: DevicePath.Type,
 915            subtype: Subtype,
 916            length: u16 align(1),
 917            start: u64 align(1),
 918            end: u64 align(1),
 919            disk_type: Guid align(1),
 920            instance: u16 align(1),
 921        };
 922
 923        comptime {
 924            assert(38 == @sizeOf(RamDiskDevicePath));
 925            assert(1 == @alignOf(RamDiskDevicePath));
 926
 927            assert(0 == @offsetOf(RamDiskDevicePath, "type"));
 928            assert(1 == @offsetOf(RamDiskDevicePath, "subtype"));
 929            assert(2 == @offsetOf(RamDiskDevicePath, "length"));
 930            assert(4 == @offsetOf(RamDiskDevicePath, "start"));
 931            assert(12 == @offsetOf(RamDiskDevicePath, "end"));
 932            assert(20 == @offsetOf(RamDiskDevicePath, "disk_type"));
 933            assert(36 == @offsetOf(RamDiskDevicePath, "instance"));
 934        }
 935    };
 936
 937    pub const BiosBootSpecification = union(Subtype) {
 938        bbs101: *const BBS101DevicePath,
 939
 940        pub const Subtype = enum(u8) {
 941            bbs101 = 1,
 942            _,
 943        };
 944
 945        pub const BBS101DevicePath = extern struct {
 946            type: DevicePath.Type,
 947            subtype: Subtype,
 948            length: u16 align(1),
 949            device_type: u16 align(1),
 950            status_flag: u16 align(1),
 951
 952            pub fn getDescription(self: *const BBS101DevicePath) [*:0]const u8 {
 953                return @as([*:0]const u8, @ptrCast(self)) + @sizeOf(BBS101DevicePath);
 954            }
 955        };
 956
 957        comptime {
 958            assert(8 == @sizeOf(BBS101DevicePath));
 959            assert(1 == @alignOf(BBS101DevicePath));
 960
 961            assert(0 == @offsetOf(BBS101DevicePath, "type"));
 962            assert(1 == @offsetOf(BBS101DevicePath, "subtype"));
 963            assert(2 == @offsetOf(BBS101DevicePath, "length"));
 964            assert(4 == @offsetOf(BBS101DevicePath, "device_type"));
 965            assert(6 == @offsetOf(BBS101DevicePath, "status_flag"));
 966        }
 967    };
 968
 969    pub const End = union(Subtype) {
 970        end_entire: *const EndEntireDevicePath,
 971        end_this_instance: *const EndThisInstanceDevicePath,
 972
 973        pub const Subtype = enum(u8) {
 974            end_entire = 0xff,
 975            end_this_instance = 0x01,
 976            _,
 977        };
 978
 979        pub const EndEntireDevicePath = extern struct {
 980            type: DevicePath.Type,
 981            subtype: Subtype,
 982            length: u16 align(1),
 983        };
 984
 985        comptime {
 986            assert(4 == @sizeOf(EndEntireDevicePath));
 987            assert(1 == @alignOf(EndEntireDevicePath));
 988
 989            assert(0 == @offsetOf(EndEntireDevicePath, "type"));
 990            assert(1 == @offsetOf(EndEntireDevicePath, "subtype"));
 991            assert(2 == @offsetOf(EndEntireDevicePath, "length"));
 992        }
 993
 994        pub const EndThisInstanceDevicePath = extern struct {
 995            type: DevicePath.Type,
 996            subtype: Subtype,
 997            length: u16 align(1),
 998        };
 999
1000        comptime {
1001            assert(4 == @sizeOf(EndEntireDevicePath));
1002            assert(1 == @alignOf(EndEntireDevicePath));
1003
1004            assert(0 == @offsetOf(EndEntireDevicePath, "type"));
1005            assert(1 == @offsetOf(EndEntireDevicePath, "subtype"));
1006            assert(2 == @offsetOf(EndEntireDevicePath, "length"));
1007        }
1008    };
1009};