Add support for hard drive nodes

This commit is contained in:
Melora Hugues 2023-09-16 17:00:46 +02:00
parent 2e97936133
commit 23ec82f4ec
6 changed files with 132 additions and 1 deletions

View file

@ -30,6 +30,8 @@ const EndOfEntireDevicePath DeviceNodeSubType = 0xFF
const ACPISubType DeviceNodeSubType = 1
const HardDriveSubType DeviceNodeSubType = 1
type DevicePathNode interface {
Type() DeviceNodeType
SubType() DeviceNodeSubType

5
go.mod
View file

@ -2,7 +2,10 @@ module git.faercol.me/faercol/devicepath
go 1.20
require github.com/stretchr/testify v1.8.4
require (
github.com/google/uuid v1.3.1
github.com/stretchr/testify v1.8.4
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect

2
go.sum
View file

@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=

105
harddrive.go Normal file
View file

@ -0,0 +1,105 @@
package devicepath
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/google/uuid"
)
const (
hdLength uint16 = 2
hdPrefix string = "HD"
)
func signatureTypeToStr(val uint8) string {
switch val {
case 1:
return "MBR"
default:
return "GPT"
}
}
func formatSignature(signature [16]byte, signatureType uint8) string {
switch signatureType {
case 1: // MBR
return fmt.Sprintf("%x", signature[:4]) // only stored on the first 4 bytes
default: // default is GPT
parsedUID, _ := uuid.FromBytes(signature[:])
return parsedUID.String()
}
}
type HardDriveDevicePath struct {
partitionNumber uint32
partitionStart uint64
partitionSize uint64
partitionSignature [16]byte
// partitionFormat uint8
signatureType uint8
}
func (hp *HardDriveDevicePath) Type() DeviceNodeType {
return MediaDevicePath
}
func (hp *HardDriveDevicePath) SubType() DeviceNodeSubType {
return HardDriveSubType
}
func (hp *HardDriveDevicePath) String() string {
return fmt.Sprintf("%s(%d,%s,%s,0x%x,0x%x)", hdPrefix, hp.partitionNumber, signatureTypeToStr(hp.signatureType), formatSignature(hp.partitionSignature, hp.signatureType), hp.partitionStart, hp.partitionSize)
}
func (hp *HardDriveDevicePath) Bytes() []byte {
return nil
}
func (hp *HardDriveDevicePath) ParseString(raw string) error {
if !checkStringFormat(raw, hdPrefix, -1) {
return ErrMalformedString
}
args := strings.Split(raw[len(hdPrefix)+1:len(raw)-1], ",")
if len(args) != 5 {
return errors.New("unexpected number of arguments")
}
if partNumber, err := strconv.ParseUint(args[0], 10, 32); err != nil {
return err
} else {
hp.partitionNumber = uint32(partNumber)
}
switch args[1] {
case "MBR":
return errors.New("MBR partitions not yet supported")
default:
hp.signatureType = 2
}
if uid, err := uuid.Parse(args[2]); err != nil {
return err
} else {
if dat, err := uid.MarshalBinary(); err != nil {
return err
} else {
hp.partitionSignature = [16]byte(dat)
}
}
if start, err := strconv.ParseUint(args[3], 0, 64); err != nil {
return err
} else {
hp.partitionStart = start
}
if size, err := strconv.ParseUint(args[4], 0, 64); err != nil {
return err
} else {
hp.partitionSize = size
}
return nil
}

18
harddrive_test.go Normal file
View file

@ -0,0 +1,18 @@
package devicepath_test
import (
"testing"
"git.faercol.me/faercol/devicepath"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestHDParseString(t *testing.T) {
t.Run("GPT", func(t *testing.T) {
expected := "HD(1,GPT,16f06d01-50da-6544-86bd-f3457f980086,0x1000,0x96000)"
var dev devicepath.HardDriveDevicePath
require.NoError(t, dev.ParseString(expected))
assert.Equal(t, expected, dev.String())
})
}

View file

@ -34,6 +34,7 @@ var prefixTypeAssociation = map[string]nodeGenerator{
sataPrefix: func() DevicePathNode { return &SataDevicePath{} },
pciPrefix: func() DevicePathNode { return &PCIDevicePath{} },
pciRootPrefix: func() DevicePathNode { return &PCIRootDevicePath{} },
hdPrefix: func() DevicePathNode { return &HardDriveDevicePath{} },
}
func Parsenode(raw string) (DevicePathNode, error) {