1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
package device
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"log"
"github.com/foxboron/go-uefi/efi/util"
)
// Subtypes of Media Device
// Section 10.3.5 - Media Device Path
const (
_ DevicePathSubType = iota
HardDriveDevicePath
CDRomDevicePath
VendorMediaDevicePath
FilePathDevicePath
MediaProtocolDevicePath
PIWGFirmwareDevicePath
)
type HardDriveMediaDevicePath struct {
EFIDevicePath
PartitionNumber uint32
PartitionStart [8]byte
PartitionSize [8]byte
PartitionSignature [16]byte
PartitionFormat uint8
SignatureType uint8
}
func (h HardDriveMediaDevicePath) Format() string {
format := []string{"MBR", "GPT"}
if h.PartitionNumber == 0 {
return fmt.Sprintf("HD(%d,%s,%x)",
h.PartitionNumber,
format[h.PartitionFormat-1],
h.PartitionSignature)
}
return fmt.Sprintf("HD(%d,%s,%s,0x%x,0x%x)",
h.PartitionNumber,
format[h.PartitionFormat-1],
util.BytesToGUID(h.PartitionSignature[:]).Format(),
binary.LittleEndian.Uint64(h.PartitionStart[:]),
binary.LittleEndian.Uint64(h.PartitionSize[:]))
}
type FileTypeMediaDevicePath struct {
EFIDevicePath
PathName string
}
func (f FileTypeMediaDevicePath) Format() string {
return fmt.Sprintf("File(%s)", f.PathName)
}
type FirmwareFielMediaDevicePath struct {
EFIDevicePath
FirmwareFileName [16]byte
}
func (f FirmwareFielMediaDevicePath) Format() string {
return "No format"
}
func ParseMediaDevicePath(f io.Reader, efi *EFIDevicePath) (EFIDevicePaths, error) {
var err error
switch efi.SubType {
case HardDriveDevicePath:
m := HardDriveMediaDevicePath{EFIDevicePath: *efi}
for _, b := range []interface{}{
&m.PartitionNumber,
&m.PartitionStart,
&m.PartitionSize,
&m.PartitionSignature,
&m.PartitionFormat,
&m.SignatureType,
} {
if err := binary.Read(f, binary.LittleEndian, b); err != nil {
return nil, fmt.Errorf("Couldn't parse Harddrive Device Path: %w", err)
}
}
return m, nil
case FilePathDevicePath:
file := FileTypeMediaDevicePath{EFIDevicePath: *efi}
b := util.ReadNullString(f)
file.PathName, err = util.ParseUtf16Var(bytes.NewBuffer(b))
if err != nil {
return nil, err
}
return file, nil
case PIWGFirmwareDevicePath:
file := FirmwareFielMediaDevicePath{EFIDevicePath: *efi}
if err := binary.Read(f, binary.LittleEndian, &file.FirmwareFileName); err != nil {
return nil, fmt.Errorf("Couldn't parse PIWG Firmware Device Path: %w", err)
}
return file, nil
default:
log.Printf("Not implemented MediaDevicePath type: %x", efi.SubType)
}
return nil, nil
}
|