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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
package bsdp
import (
"fmt"
"github.com/insomniacslk/dhcp/dhcpv4"
"github.com/u-root/u-root/pkg/uio"
)
// BootImageType represents the different BSDP boot image types.
type BootImageType byte
// Different types of BootImages - e.g. for different flavors of macOS.
const (
BootImageTypeMacOS9 BootImageType = 0
BootImageTypeMacOSX BootImageType = 1
BootImageTypeMacOSXServer BootImageType = 2
BootImageTypeHardwareDiagnostics BootImageType = 3
// 4 - 127 are reserved for future use.
)
// bootImageTypeToString maps the different BootImageTypes to human-readable
// representations.
var bootImageTypeToString = map[BootImageType]string{
BootImageTypeMacOS9: "macOS 9",
BootImageTypeMacOSX: "macOS",
BootImageTypeMacOSXServer: "macOS Server",
BootImageTypeHardwareDiagnostics: "Hardware Diagnostic",
}
// BootImageID describes a boot image ID - whether it's an install image and
// what kind of boot image (e.g. OS 9, macOS, hardware diagnostics)
type BootImageID struct {
IsInstall bool
ImageType BootImageType
Index uint16
}
// ToBytes implements dhcpv4.OptionValue.
func (b BootImageID) ToBytes() []byte {
return uio.ToBigEndian(b)
}
// FromBytes reads data into b.
func (b *BootImageID) FromBytes(data []byte) error {
return uio.FromBigEndian(b, data)
}
// Marshal writes the binary representation to buf.
func (b BootImageID) Marshal(buf *uio.Lexer) {
var byte0 byte
if b.IsInstall {
byte0 |= 0x80
}
byte0 |= byte(b.ImageType)
buf.Write8(byte0)
buf.Write8(byte(0))
buf.Write16(b.Index)
}
// String converts a BootImageID to a human-readable representation.
func (b BootImageID) String() string {
s := fmt.Sprintf("[%d]", b.Index)
if b.IsInstall {
s += " installable"
} else {
s += " uninstallable"
}
t, ok := bootImageTypeToString[b.ImageType]
if !ok {
t = "unknown"
}
return s + " " + t + " image"
}
// Unmarshal reads b's binary representation from buf.
func (b *BootImageID) Unmarshal(buf *uio.Lexer) error {
byte0 := buf.Read8()
_ = buf.Read8()
b.IsInstall = byte0&0x80 != 0
b.ImageType = BootImageType(byte0 & 0x7f)
b.Index = buf.Read16()
return buf.Error()
}
// BootImage describes a boot image - contains the boot image ID and the name.
type BootImage struct {
ID BootImageID
Name string
}
// Marshal write a BootImage to buf.
func (b BootImage) Marshal(buf *uio.Lexer) {
b.ID.Marshal(buf)
buf.Write8(uint8(len(b.Name)))
buf.WriteBytes([]byte(b.Name))
}
// String converts a BootImage to a human-readable representation.
func (b BootImage) String() string {
return fmt.Sprintf("%v %v", b.Name, b.ID.String())
}
// Unmarshal reads data from buf into b.
func (b *BootImage) Unmarshal(buf *uio.Lexer) error {
if err := (&b.ID).Unmarshal(buf); err != nil {
return err
}
nameLength := buf.Read8()
b.Name = string(buf.Consume(int(nameLength)))
return buf.Error()
}
func getBootImageID(code dhcpv4.OptionCode, o dhcpv4.Options) *BootImageID {
v := o.Get(code)
if v == nil {
return nil
}
var b BootImageID
if err := uio.FromBigEndian(&b, v); err != nil {
return nil
}
return &b
}
// OptDefaultBootImageID returns a new default boot image ID option as per
// BSDP.
func OptDefaultBootImageID(b BootImageID) dhcpv4.Option {
return dhcpv4.Option{Code: OptionDefaultBootImageID, Value: b}
}
// OptSelectedBootImageID returns a new selected boot image ID option as per
// BSDP.
func OptSelectedBootImageID(b BootImageID) dhcpv4.Option {
return dhcpv4.Option{Code: OptionSelectedBootImageID, Value: b}
}
|