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/uio/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}
}
|