[dumpregisters] Dump registers in a human-readable YAML
This commit is contained in:
parent
ec7b2c5e5d
commit
9e8b4def11
|
@ -1,18 +1,21 @@
|
|||
package dumpregisters
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/9elements/converged-security-suite/v2/cmd/pcr0tool/commands/dumpregisters/helpers"
|
||||
"github.com/9elements/converged-security-suite/v2/pkg/registers"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Command is the implementation of `commands.Command`.
|
||||
type Command struct {
|
||||
outputFile *string
|
||||
txtPublicDump *string
|
||||
registers helpers.FlagRegisters
|
||||
}
|
||||
|
||||
// Usage prints the syntax of arguments for this command
|
||||
|
@ -32,6 +35,7 @@ func (cmd *Command) SetupFlagSet(flag *flag.FlagSet) {
|
|||
"[optional] dumps all registers into a file")
|
||||
cmd.txtPublicDump = flag.String("txt-public-dump", "",
|
||||
"[optional] override TXT public space with a file")
|
||||
flag.Var(&cmd.registers, "registers", "[optional] file that contains registers as a json array (use value '/dev' to use registers of the local machine)")
|
||||
}
|
||||
|
||||
// Execute is the main function here. It is responsible to
|
||||
|
@ -39,18 +43,29 @@ func (cmd *Command) SetupFlagSet(flag *flag.FlagSet) {
|
|||
//
|
||||
// `args` are the arguments left unused by verb itself and options.
|
||||
func (cmd Command) Execute(args []string) {
|
||||
getRegistersOpts := []helpers.GetRegistersOption{helpers.OptLocalhostByDefault(true)}
|
||||
if *cmd.txtPublicDump != "" {
|
||||
getRegistersOpts = append(getRegistersOpts, helpers.OptTXTPublic(*cmd.txtPublicDump))
|
||||
if *cmd.txtPublicDump != "" && cmd.registers != nil {
|
||||
panic(fmt.Errorf("cannot use flags -txt-public-dump and -registers together"))
|
||||
}
|
||||
var (
|
||||
regs registers.Registers
|
||||
err error
|
||||
)
|
||||
if cmd.registers != nil {
|
||||
regs = registers.Registers(cmd.registers)
|
||||
} else {
|
||||
getRegistersOpts := []helpers.GetRegistersOption{helpers.OptLocalhostByDefault(true)}
|
||||
if *cmd.txtPublicDump != "" {
|
||||
getRegistersOpts = append(getRegistersOpts, helpers.OptTXTPublic(*cmd.txtPublicDump))
|
||||
}
|
||||
regs, err = helpers.GetRegisters(getRegistersOpts...)
|
||||
}
|
||||
regs, err := helpers.GetRegisters(getRegistersOpts...)
|
||||
if regs == nil && err != nil {
|
||||
panic(err)
|
||||
}
|
||||
helpers.PrintRegisters(regs)
|
||||
|
||||
if len(*cmd.outputFile) > 0 {
|
||||
b, err := json.Marshal(regs)
|
||||
b, err := yaml.Marshal(regs)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to marshal registers into json, err: %v", err))
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"io/ioutil"
|
||||
|
||||
"github.com/9elements/converged-security-suite/v2/pkg/registers"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// FlagRegisters is a flag.Value implementation to enter status registers.
|
||||
|
@ -39,9 +40,19 @@ func (f *FlagRegisters) Set(in string) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("unable to parse file '%s': %w", in, err)
|
||||
}
|
||||
|
||||
// ===
|
||||
// TODO: Remove the JSON format, it is added only for backward compatibility
|
||||
// In year like 2025 this should be deleted.
|
||||
err = json.Unmarshal(contents, (*registers.Registers)(f))
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
// ===
|
||||
|
||||
err = yaml.Unmarshal(contents, (*registers.Registers)(f))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal JSON from file '%s': %w", in, err)
|
||||
return fmt.Errorf("unable to unmarshal YAML from file '%s': %w", in, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
1
go.mod
1
go.mod
|
@ -30,6 +30,7 @@ require (
|
|||
github.com/xaionaro-go/bytesextra v0.0.0-20220103144954-846e454ddea9
|
||||
github.com/xaionaro-go/unsafetools v0.0.0-20210722164218-75ba48cf7b3c
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
replace github.com/9elements/converged-security-suite/v2/testdata/firmware => ./testdata/firmware
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package registers
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func valueToHex(vRaw interface{}) string {
|
||||
v := reflect.ValueOf(vRaw)
|
||||
switch {
|
||||
case v.Type().ConvertibleTo(reflect.TypeOf(uint64(0))):
|
||||
i := v.Convert(reflect.TypeOf(uint64(0))).Interface().(uint64)
|
||||
return "0x" + strconv.FormatUint(i, 16)
|
||||
case v.Type().ConvertibleTo(reflect.TypeOf([]byte(nil))):
|
||||
b := v.Convert(reflect.TypeOf([]byte(nil))).Interface().([]byte)
|
||||
return "0x" + hex.EncodeToString(b)
|
||||
}
|
||||
panic(fmt.Sprintf("unknown type: %T", vRaw))
|
||||
}
|
||||
|
||||
func valueUnpack(regID RegisterID, v interface{}) (interface{}, error) {
|
||||
switch v := v.(type) {
|
||||
case uint8, uint16, uint32, uint64, uint, int:
|
||||
return v, nil
|
||||
case string:
|
||||
return valueUnpackString(regID, v)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown value type: %T", v)
|
||||
}
|
||||
}
|
||||
|
||||
func valueUnpackString(regID RegisterID, s string) (interface{}, error) {
|
||||
switch {
|
||||
case strings.HasPrefix(s, "0x"):
|
||||
return valueFromHex(regID, s[2:])
|
||||
case strings.HasPrefix(s, "base64:"): // TODO: obsolete format, remove it
|
||||
return valueFromBase64(regID, s[7:])
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown prefix in string: '%s'", s)
|
||||
}
|
||||
}
|
||||
|
||||
func valueFromHex(regID RegisterID, h string) (interface{}, error) {
|
||||
regSample, err := registry.New(regID, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create a value for register %v: %w", regID, err)
|
||||
}
|
||||
v := reflect.New(reflect.TypeOf(regSample.Value())).Elem()
|
||||
switch {
|
||||
case v.Type().ConvertibleTo(reflect.TypeOf(uint64(0))):
|
||||
i, err := strconv.ParseUint(h, 16, int(v.Type().Size())*8)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse hex '%s' to int: %w", h, err)
|
||||
}
|
||||
v.SetUint(i)
|
||||
case v.Type().ConvertibleTo(reflect.TypeOf([]byte(nil))):
|
||||
b, err := hex.DecodeString(h)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid hex '%s': %w", h, err)
|
||||
}
|
||||
v.SetBytes(b)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown type: %T", regSample)
|
||||
}
|
||||
return v.Interface(), nil
|
||||
}
|
||||
|
||||
// TODO: delete this function
|
||||
func valueFromBase64(regID RegisterID, b64 string) (interface{}, error) {
|
||||
b, err := base64.StdEncoding.DecodeString(b64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decode base64 string '%s': %w", b64, err)
|
||||
}
|
||||
return ValueFromBytes(regID, b)
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
// TODO: delete this file, it uses obsolete serialization code,
|
||||
// now we use HEX instead of Base64, see marshal_value.go
|
||||
|
||||
package registers
|
||||
|
||||
import (
|
||||
|
@ -6,8 +9,9 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
// MarshalValue puts register's internal value into a sequence of bytes
|
||||
func MarshalValue(reg Register) ([]byte, error) {
|
||||
// ValueBytes puts register's internal value into a sequence of bytes
|
||||
// TODO: use dynamic conversion instead of hard-code
|
||||
func ValueBytes(reg Register) ([]byte, error) {
|
||||
if reg == nil {
|
||||
return nil, fmt.Errorf("input register is nil")
|
||||
}
|
||||
|
@ -150,13 +154,14 @@ func getRegister8Parser(regID RegisterID) func(ui8 uint8) Register {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal constructs register from it's id and marshalled value
|
||||
func Unmarshal(id RegisterID, b []byte) (Register, error) {
|
||||
// ValueFromBytes constructs register from it's id and marshalled value
|
||||
// TODO: use dynamic conversion instead of hard-code
|
||||
func ValueFromBytes(id RegisterID, b []byte) (Register, error) {
|
||||
// special case registers
|
||||
switch id {
|
||||
case TXTPublicKeyRegisterID:
|
||||
if len(b) != 32 {
|
||||
return nil, fmt.Errorf("incorrect input bytes length, 32 is expected, but got %d", len(b))
|
||||
return nil, fmt.Errorf("incorrect input bytes length, 32 is expected, but got %d ('%s')", len(b), b)
|
||||
}
|
||||
var arr [32]byte
|
||||
copy(arr[:], b[:])
|
||||
|
|
|
@ -43,12 +43,12 @@ func TestMarshalUnmarshal(t *testing.T) {
|
|||
|
||||
regs := append(txtRegisters, append(amdRegisters, msrRegisters...)...)
|
||||
for _, reg := range regs {
|
||||
rawValue, err := registers.MarshalValue(reg)
|
||||
rawValue, err := registers.ValueBytes(reg)
|
||||
if err != nil {
|
||||
t.Errorf("failed to marhal register's %s value, err: %v", reg.ID(), err)
|
||||
continue
|
||||
}
|
||||
result, err := registers.Unmarshal(reg.ID(), rawValue)
|
||||
result, err := registers.ValueFromBytes(reg.ID(), rawValue)
|
||||
if err != nil {
|
||||
t.Errorf("failed to unmarhal register %s, err: %v", reg.ID(), err)
|
||||
continue
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(MP0C2PMsg37(0))
|
||||
}
|
||||
|
||||
const MP0C2PMSG37RegisterID RegisterID = "MP0_C2P_MSG_37"
|
||||
|
||||
type MP0C2PMsg37 uint32
|
||||
|
@ -33,6 +37,11 @@ func (r MP0C2PMsg37) Fields() []Field {
|
|||
return CalculateRegisterFields(uint64(r.Raw()), r.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (r MP0C2PMsg37) Value() interface{} {
|
||||
return r.Raw()
|
||||
}
|
||||
|
||||
// Raw returns the raw value of of MP0_C2P_MSG_37 register
|
||||
func (r MP0C2PMsg37) Raw() uint32 {
|
||||
return uint32(r)
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(MP0C2PMsg38(0))
|
||||
}
|
||||
|
||||
const MP0C2PMSG38RegisterID RegisterID = "MP0_C2P_MSG_38"
|
||||
|
||||
type MP0C2PMsg38 uint32
|
||||
|
@ -25,6 +29,11 @@ func (r MP0C2PMsg38) Fields() []Field {
|
|||
return CalculateRegisterFields(uint64(r.Raw()), r.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (r MP0C2PMsg38) Value() interface{} {
|
||||
return r.Raw()
|
||||
}
|
||||
|
||||
// Raw returns the raw value of of MP0_C2P_MSG_37 register
|
||||
func (r MP0C2PMsg38) Raw() uint32 {
|
||||
return uint32(r)
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(BootGuardPBEC(0))
|
||||
}
|
||||
|
||||
const BootGuardPBECRegisterID = "BOOT_GUARD_PBEC"
|
||||
const BootGuardPBECRegisterOffset = 0x139
|
||||
|
||||
|
@ -31,6 +35,11 @@ func (reg BootGuardPBEC) Fields() []Field {
|
|||
return CalculateRegisterFields(reg.Raw(), reg.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg BootGuardPBEC) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg BootGuardPBEC) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(BTGSACMInfo(0))
|
||||
}
|
||||
|
||||
const BTGSACMInfoRegisterID = "BTG_SACM_INFO"
|
||||
const BTGSACMInfoRegisterOffset = 0x13A
|
||||
|
||||
|
@ -75,6 +79,11 @@ func (reg BTGSACMInfo) Fields() []Field {
|
|||
return CalculateRegisterFields(reg.Raw(), reg.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg BTGSACMInfo) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg BTGSACMInfo) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(IA32DebugInterface(0))
|
||||
}
|
||||
|
||||
const IA32DebugInterfaceRegisterID = "IA32_DEBUG_INTERFACE"
|
||||
const IA32DebugInterfaceRegisterOffset = 0xC80
|
||||
|
||||
|
@ -43,6 +47,11 @@ func (reg IA32DebugInterface) Fields() []Field {
|
|||
return CalculateRegisterFields(reg.Raw(), reg.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg IA32DebugInterface) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg IA32DebugInterface) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(IA32FeatureControl(0))
|
||||
}
|
||||
|
||||
const IA32FeatureControlRegisterID = "IA32_FEATURE_CONTROL"
|
||||
const IA32FeatureControlRegisterOffset = 0x3A
|
||||
|
||||
|
@ -20,7 +24,7 @@ func (reg IA32FeatureControl) Address() uint64 {
|
|||
func (reg IA32FeatureControl) Fields() []Field {
|
||||
fieldsRaw := []FieldDescription{
|
||||
{
|
||||
Name: "Lock (0 =unlocked, 1 = locked)",
|
||||
Name: "Lock (0 = unlocked, 1 = locked)",
|
||||
BitOffset: 0,
|
||||
},
|
||||
{
|
||||
|
@ -51,6 +55,11 @@ func (reg IA32FeatureControl) Fields() []Field {
|
|||
return CalculateRegisterFields(reg.Raw(), reg.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg IA32FeatureControl) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg IA32FeatureControl) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(IA32MTRRCAP(0))
|
||||
}
|
||||
|
||||
const IA32MTRRCAPRegisterID = "IA32_MTRRCAP"
|
||||
const IA32MTRRCAPRegisterOffset = 0xfe
|
||||
|
||||
|
@ -63,6 +67,11 @@ func (reg IA32MTRRCAP) SMRRInterfaceSupported() bool {
|
|||
return (reg>>11)&0x1 != 0
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg IA32MTRRCAP) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg IA32MTRRCAP) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(IA32PlatformID(0))
|
||||
}
|
||||
|
||||
const IA32PlatformIDRegisterID = "IA32_PLATFORM_ID"
|
||||
const IA32PlatformIDRegisterOffset = 0x17
|
||||
|
||||
|
@ -35,6 +39,11 @@ func (reg IA32PlatformID) Fields() []Field {
|
|||
return CalculateRegisterFields(reg.Raw(), reg.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg IA32PlatformID) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg IA32PlatformID) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(IA32SMRRPhysBase(0))
|
||||
}
|
||||
|
||||
const IA32SMRRPhysBaseRegisterID = "IA32_SMRR_PHYSBASE"
|
||||
const IA32SMRRPhysBaseRegisterOffset = 0x1F2
|
||||
|
||||
|
@ -39,6 +43,11 @@ func (reg IA32SMRRPhysBase) Fields() []Field {
|
|||
return CalculateRegisterFields(reg.Raw(), reg.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg IA32SMRRPhysBase) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg IA32SMRRPhysBase) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package registers
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(IA32SMRRPhysMask(0))
|
||||
}
|
||||
|
||||
const IA32SMRRPhysMaskRegisterID = "IA32_SMRR_PHYSMASK"
|
||||
const IA32SMRRPhysMaskRegisterOffset = 0x1F3
|
||||
|
||||
|
@ -39,6 +43,11 @@ func (reg IA32SMRRPhysMask) Fields() []Field {
|
|||
return CalculateRegisterFields(reg.Raw(), reg.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg IA32SMRRPhysMask) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg IA32SMRRPhysMask) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
package registers
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// RegisterID is a unique id of a register (either TXT or MSR)
|
||||
type RegisterID string
|
||||
|
@ -11,6 +17,7 @@ type Register interface {
|
|||
BitSize() uint8
|
||||
Fields() []Field
|
||||
Address() uint64
|
||||
Value() interface{}
|
||||
}
|
||||
|
||||
// RawRegister is a simple accessor to variable length registers
|
||||
|
@ -43,6 +50,12 @@ type RawRegister64 interface {
|
|||
Raw() uint64
|
||||
}
|
||||
|
||||
// New constructs a register, given its ID and raw value. It
|
||||
// will return an error if the value is of wrong underlying type.
|
||||
func New(regID RegisterID, value interface{}) (Register, error) {
|
||||
return registry.New(regID, value)
|
||||
}
|
||||
|
||||
// Registers represents an abstract collection of some registers
|
||||
type Registers []Register
|
||||
|
||||
|
@ -57,42 +70,138 @@ func (regs Registers) Find(id RegisterID) Register {
|
|||
return nil
|
||||
}
|
||||
|
||||
type registerJSON struct {
|
||||
type registerForSerializationOBSOLETE struct {
|
||||
ID RegisterID `json:"id"`
|
||||
Value []byte `json:"value"`
|
||||
}
|
||||
|
||||
// MarshalJSON converts a collection of registers into a JSON
|
||||
func (regs Registers) MarshalJSON() ([]byte, error) {
|
||||
resultRegisters := make([]registerJSON, 0, len(regs))
|
||||
for _, reg := range regs {
|
||||
v, err := MarshalValue(reg)
|
||||
type registersForSerializationOBSOLETE []registerForSerializationOBSOLETE
|
||||
|
||||
func (regs registersForSerializationOBSOLETE) ParseRegisters() (Registers, error) {
|
||||
resultRegisters := make(Registers, 0, len(regs))
|
||||
for idx, regS := range regs {
|
||||
v, err := ValueFromBytes(regS.ID, regS.Value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to un-base64 value %d:'%s': %w", idx, regS.Value, err)
|
||||
}
|
||||
reg, err := New(regS.ID, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultRegisters = append(resultRegisters, registerJSON{
|
||||
resultRegisters = append(resultRegisters, reg)
|
||||
}
|
||||
return resultRegisters, nil
|
||||
}
|
||||
|
||||
func (regs Registers) forSerializationOBSOLETE() (registersForSerializationOBSOLETE, error) {
|
||||
resultRegisters := make(registersForSerializationOBSOLETE, 0, len(regs))
|
||||
for _, reg := range regs {
|
||||
b, err := ValueBytes(reg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to serialize the value of register %T:%v", reg, reg)
|
||||
}
|
||||
resultRegisters = append(resultRegisters, registerForSerializationOBSOLETE{
|
||||
ID: reg.ID(),
|
||||
Value: v,
|
||||
Value: b,
|
||||
})
|
||||
}
|
||||
return json.Marshal(resultRegisters)
|
||||
return resultRegisters, nil
|
||||
}
|
||||
|
||||
// MarshalJSON converts a collection of registers into a JSON
|
||||
// TODO: remove this, obsolete format
|
||||
// OBSOLETE
|
||||
func (regs Registers) MarshalJSON() ([]byte, error) {
|
||||
v, err := regs.forSerializationOBSOLETE()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
// UnmarshalJSON parses registers from JSON that was previously obtained using MarshalJSON
|
||||
// TODO: remove this, obsolete format
|
||||
// OBSOLETE
|
||||
func (regs *Registers) UnmarshalJSON(b []byte) error {
|
||||
var jsonRegisters []registerJSON
|
||||
var jsonRegisters registersForSerializationOBSOLETE
|
||||
if err := json.Unmarshal(b, &jsonRegisters); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to un-JSON-ize registers: %w", err)
|
||||
}
|
||||
|
||||
resultRegisters := make(Registers, 0, len(jsonRegisters))
|
||||
for _, jsonReg := range jsonRegisters {
|
||||
reg, err := Unmarshal(jsonReg.ID, jsonReg.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resultRegisters = append(resultRegisters, reg)
|
||||
resultRegisters, err := jsonRegisters.ParseRegisters()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to convert registers: %w", err)
|
||||
}
|
||||
*regs = resultRegisters
|
||||
return nil
|
||||
}
|
||||
|
||||
type registersForSerialization map[RegisterID]interface{}
|
||||
|
||||
func (m registersForSerialization) Registers() (Registers, error) {
|
||||
resultRegisters := make(Registers, 0, len(m))
|
||||
for regID, serializedValue := range m {
|
||||
v, err := valueUnpack(regID, serializedValue)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to unpack value '%s': %w", serializedValue, err)
|
||||
}
|
||||
reg, err := New(regID, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultRegisters = append(resultRegisters, reg)
|
||||
}
|
||||
resultRegisters.Sort()
|
||||
return resultRegisters, nil
|
||||
}
|
||||
|
||||
// Sort sorts registers in some stable manner
|
||||
func (regs Registers) Sort() {
|
||||
sort.Slice(regs, func(i, j int) bool {
|
||||
a0 := regs[i].Address()
|
||||
a1 := regs[j].Address()
|
||||
if a0 != a1 {
|
||||
return a0 < a1
|
||||
}
|
||||
return regs[i].ID() < regs[j].ID()
|
||||
})
|
||||
}
|
||||
|
||||
func (regs Registers) forSerialization() (registersForSerialization, error) {
|
||||
m := make(registersForSerialization, len(regs))
|
||||
for _, reg := range regs {
|
||||
m[reg.ID()] = valueToHex(reg.Value())
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// MarshalYAML converts a collection of registers into an YAML
|
||||
func (regs Registers) MarshalYAML() (interface{}, error) {
|
||||
v, err := regs.forSerialization()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to prepare a serializable data structure: %w", err)
|
||||
}
|
||||
|
||||
n := &yaml.Node{}
|
||||
if err := n.Encode(v); err != nil {
|
||||
return nil, fmt.Errorf("unable to encode to YAML: %w", err)
|
||||
}
|
||||
for _, regYaml := range n.Content {
|
||||
regYaml.Style = yaml.TaggedStyle
|
||||
regYaml.Tag = ""
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// UnmarshalYAML parses registers from YAML that was previously obtained using MarshalYAML
|
||||
func (regs *Registers) UnmarshalYAML(value *yaml.Node) error {
|
||||
var regsYaml registersForSerialization
|
||||
if err := value.Decode(®sYaml); err != nil {
|
||||
return fmt.Errorf("unable to un-YAML-ize registers: %w", err)
|
||||
}
|
||||
result, err := regsYaml.Registers()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse registers data: %w", err)
|
||||
}
|
||||
*regs = result
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,16 +2,25 @@ package registers_test
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/9elements/converged-security-suite/v2/pkg/registers"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/9elements/converged-security-suite/v2/pkg/registers"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func TestJSONMarshaling(t *testing.T) {
|
||||
initialRegisters := registers.Registers{
|
||||
func registersSample() registers.Registers {
|
||||
regs := registers.Registers{
|
||||
registers.ParseACMPolicyStatusRegister(0x42),
|
||||
registers.ParseIA32SMRRPhysBase(42),
|
||||
registers.ParseTXTPublicKey([32]byte{1, 2, 3}),
|
||||
}
|
||||
regs.Sort()
|
||||
return regs
|
||||
}
|
||||
|
||||
func TestOBSOLETEJSONMarshaling(t *testing.T) {
|
||||
initialRegisters := registersSample()
|
||||
|
||||
b, err := json.Marshal(initialRegisters)
|
||||
if err != nil {
|
||||
|
@ -29,3 +38,23 @@ func TestJSONMarshaling(t *testing.T) {
|
|||
t.Errorf("result registers %v are not equal to the initial %v", initialRegisters, resultRegisters)
|
||||
}
|
||||
}
|
||||
|
||||
func TestYAMLMarshaling(t *testing.T) {
|
||||
initialRegisters := registersSample()
|
||||
|
||||
b, err := yaml.Marshal(initialRegisters)
|
||||
if err != nil {
|
||||
t.Errorf("failed to marshal registers to YAML, err: %v", err)
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
var resultRegisters registers.Registers
|
||||
if err := yaml.Unmarshal(b, &resultRegisters); err != nil {
|
||||
t.Errorf("failed to unmarshal registers from YAML, err: %v", err)
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(initialRegisters, resultRegisters) {
|
||||
t.Errorf("result registers %v are not equal to the initial %v", initialRegisters, resultRegisters)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package registers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type registryT struct {
|
||||
idToType map[RegisterID]reflect.Type
|
||||
}
|
||||
|
||||
var registry = registryT{
|
||||
idToType: make(map[RegisterID]reflect.Type),
|
||||
}
|
||||
|
||||
// AddRegister remembers the register type and ID.
|
||||
func (registry registryT) AddRegister(reg Register) {
|
||||
registry.idToType[reg.ID()] = reflect.TypeOf(reg)
|
||||
}
|
||||
|
||||
// New constructs a register, given its ID and raw value. It
|
||||
// will return an error if the value is of wrong underlying type.
|
||||
func (registry registryT) New(regID RegisterID, value interface{}) (Register, error) {
|
||||
regT := registry.idToType[regID]
|
||||
regV := reflect.New(regT).Elem()
|
||||
if value == nil {
|
||||
return regV.Interface().(Register), nil
|
||||
}
|
||||
|
||||
valV := reflect.ValueOf(value)
|
||||
switch {
|
||||
case valV.Type().ConvertibleTo(regT):
|
||||
regV.Set(valV.Convert(regT))
|
||||
case regV.Kind() == reflect.Array && regV.Type().Elem().Kind() == reflect.Uint8:
|
||||
copy(regV.Slice(0, regV.Cap()).Interface().([]byte), valV.Interface().([]byte))
|
||||
default:
|
||||
return nil, fmt.Errorf("%T is not convertible to %s", value, regT.Name())
|
||||
}
|
||||
return regV.Interface().(Register), nil
|
||||
}
|
|
@ -6,6 +6,10 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(ACMPolicyStatus(0))
|
||||
}
|
||||
|
||||
const AcmPolicyStatusRegisterID RegisterID = "ACM_POLICY_STATUS"
|
||||
const ACMPolicyStatusRegisterOffset = 0x378
|
||||
|
||||
|
@ -49,6 +53,11 @@ func (reg ACMPolicyStatus) ID() RegisterID {
|
|||
return AcmPolicyStatusRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg ACMPolicyStatus) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg ACMPolicyStatus) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(ACMStatus(0))
|
||||
}
|
||||
|
||||
const ACMStatusRegisterID RegisterID = "ACM_STATUS"
|
||||
const ACMStatusRegisterOffset = 0x328
|
||||
|
||||
|
@ -57,12 +61,13 @@ func (reg ACMStatus) Fields() []Field {
|
|||
return CalculateRegisterFields(reg.Raw(), reg.BitSize(), fieldsRaw)
|
||||
}
|
||||
|
||||
func (reg ACMStatus) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg ACMStatus) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg ACMStatus) String() string {
|
||||
panic("Not implemented")
|
||||
func (reg ACMStatus) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
||||
func (reg ACMStatus) ModuleType() uint8 {
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTBootStatus(0))
|
||||
}
|
||||
|
||||
const TXTBootStatusRegisterID RegisterID = "TXT.SPAD"
|
||||
const TXTBootStatusRegisterOffset = 0xA0
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTBootStatus) ID() RegisterID {
|
|||
return TXTBootStatusRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTBootStatus) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTBootStatus) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTDeviceID(0))
|
||||
}
|
||||
|
||||
const TXTDeviceIDRegisterID RegisterID = "TXT.DIDVID"
|
||||
const TXTDeviceIDRegisterOffset = 0x110
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTDeviceID) ID() RegisterID {
|
|||
return TXTDeviceIDRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTDeviceID) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTDeviceID) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTDMAProtectedRange(0))
|
||||
}
|
||||
|
||||
const TXTDMAProtectedRangeRegisterID RegisterID = "TXT.DPR"
|
||||
const TXTDMAProtectedRangeRegisterOffset = 0x330
|
||||
|
||||
|
@ -23,6 +27,11 @@ func (reg TXTDMAProtectedRange) ID() RegisterID {
|
|||
return TXTDMAProtectedRangeRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTDMAProtectedRange) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTDMAProtectedRange) Raw() uint32 {
|
||||
return uint32(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTErrorCode(0))
|
||||
}
|
||||
|
||||
const TXTErrorCodeRegisterID RegisterID = "TXT.ERRORCODE"
|
||||
const TXTErrorCodeRegisterOffset = 0x30
|
||||
|
||||
|
@ -22,6 +26,11 @@ func (reg TXTErrorCode) ID() RegisterID {
|
|||
return TXTErrorCodeRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTErrorCode) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTErrorCode) Raw() uint32 {
|
||||
return uint32(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTErrorStatus(0))
|
||||
}
|
||||
|
||||
const TXTErrorStatusRegisterID RegisterID = "TXT.ESTS"
|
||||
const TXTErrorStatusRegisterOffset = 0x8
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTErrorStatus) ID() RegisterID {
|
|||
return TXTErrorStatusRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTErrorStatus) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTErrorStatus) Raw() uint8 {
|
||||
return uint8(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTHeapBase(0))
|
||||
}
|
||||
|
||||
const TXTHeapBaseRegisterID RegisterID = "TXT.HEAP.BASE"
|
||||
const TXTHeapBaseRegisterOffset = 0x300
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTHeapBase) ID() RegisterID {
|
|||
return TXTHeapBaseRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTHeapBase) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTHeapBase) Raw() uint32 {
|
||||
return uint32(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTHeapSize(0))
|
||||
}
|
||||
|
||||
const TXTHeapSizeRegisterID RegisterID = "TXT.HEAP.SIZE"
|
||||
const TXTHeapSizeRegisterOffset = 0x308
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTHeapSize) ID() RegisterID {
|
|||
return TXTHeapSizeRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTHeapSize) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTHeapSize) Raw() uint32 {
|
||||
return uint32(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTMLEJoin(0))
|
||||
}
|
||||
|
||||
const TXTMLEJoinRegisterID RegisterID = "TXT.MLE.JOIN"
|
||||
const TXTMLEJoinRegisterOffset = 0x290
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTMLEJoin) ID() RegisterID {
|
|||
return TXTMLEJoinRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTMLEJoin) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTMLEJoin) Raw() uint32 {
|
||||
return uint32(reg)
|
||||
}
|
||||
|
|
|
@ -3,21 +3,33 @@ package registers
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTPublicKey{})
|
||||
}
|
||||
|
||||
const TXTPublicKeyRegisterID RegisterID = "TXT.PUBLIC.KEY"
|
||||
const TXTPublicKeyRegisterOffset = 0x400
|
||||
|
||||
type TXTPublicKey struct {
|
||||
publicKey [32]uint8
|
||||
}
|
||||
type TXTPublicKey [32]uint8
|
||||
|
||||
func (reg TXTPublicKey) ID() RegisterID {
|
||||
return TXTPublicKeyRegisterID
|
||||
}
|
||||
|
||||
func (reg TXTPublicKey) String() string {
|
||||
return fmt.Sprintf("0x%x", reg[:])
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTPublicKey) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTPublicKey) Raw() []byte {
|
||||
return reg.publicKey[:]
|
||||
return reg[:]
|
||||
}
|
||||
|
||||
func (reg TXTPublicKey) BitSize() uint8 {
|
||||
|
@ -47,7 +59,7 @@ var _ RawRegister = TXTPublicKey{}
|
|||
func ReadTXTPublicKeyRegister(data TXTConfigSpace) (TXTPublicKey, error) {
|
||||
buf := bytes.NewReader(data[TXTPublicKeyRegisterOffset:])
|
||||
var register TXTPublicKey
|
||||
if err := binary.Read(buf, binary.LittleEndian, ®ister.publicKey); err != nil {
|
||||
if err := binary.Read(buf, binary.LittleEndian, ®ister); err != nil {
|
||||
return register, err
|
||||
}
|
||||
return register, nil
|
||||
|
@ -55,9 +67,7 @@ func ReadTXTPublicKeyRegister(data TXTConfigSpace) (TXTPublicKey, error) {
|
|||
|
||||
// ParseTXTPublicKey returns TXTPublicKey from a raw 64bit value
|
||||
func ParseTXTPublicKey(raw [32]uint8) TXTPublicKey {
|
||||
return TXTPublicKey{
|
||||
publicKey: raw,
|
||||
}
|
||||
return TXTPublicKey(raw)
|
||||
}
|
||||
|
||||
// FindTXTPublicKey returns TXTPublicKey register if found
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTSInitBase(0))
|
||||
}
|
||||
|
||||
const TXTSINITBaseRegisterID RegisterID = "TXT.SINIT.BASE"
|
||||
const TXTSINITBaseRegisterOffset = 0x270
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTSInitBase) ID() RegisterID {
|
|||
return TXTSINITBaseRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTSInitBase) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTSInitBase) Raw() uint32 {
|
||||
return uint32(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTSInitSize(0))
|
||||
}
|
||||
|
||||
const TXTSINITSizeRegisterID RegisterID = "TXT.SINIT.SIZE"
|
||||
const TXTSINITSizeRegisterOffset = 0x278
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTSInitSize) ID() RegisterID {
|
|||
return TXTSINITSizeRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTSInitSize) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTSInitSize) Raw() uint32 {
|
||||
return uint32(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTStatus(0))
|
||||
}
|
||||
|
||||
const TXTStatusRegisterID RegisterID = "TXT.STS"
|
||||
const TXTStatusRegisterOffset = 0
|
||||
|
||||
|
@ -15,6 +19,11 @@ func (reg TXTStatus) ID() RegisterID {
|
|||
return TXTStatusRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTStatus) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTStatus) Raw() uint64 {
|
||||
return uint64(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTVerEMIF(0))
|
||||
}
|
||||
|
||||
const TXTVerEMIfRegisterID RegisterID = "TXT.VER.EMIF"
|
||||
const TXTVerEMIfRegisterOffset = 0x200
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTVerEMIF) ID() RegisterID {
|
|||
return TXTVerEMIfRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTVerEMIF) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTVerEMIF) Raw() uint32 {
|
||||
return uint32(reg)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import (
|
|||
"encoding/binary"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.AddRegister(TXTVerFSBIF(0))
|
||||
}
|
||||
|
||||
const TXTVerFSBIfRegisterID RegisterID = "TXT.VER.FSBIF"
|
||||
const TXTVerFSBIfRegisterOffset = 0x100
|
||||
|
||||
|
@ -14,6 +18,11 @@ func (reg TXTVerFSBIF) ID() RegisterID {
|
|||
return TXTVerFSBIfRegisterID
|
||||
}
|
||||
|
||||
// Value returns the raw value wrapped into an interface.
|
||||
func (reg TXTVerFSBIF) Value() interface{} {
|
||||
return reg.Raw()
|
||||
}
|
||||
|
||||
func (reg TXTVerFSBIF) Raw() uint32 {
|
||||
return uint32(reg)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue