This replaces an external toml library with a simple parser for unmarshalling a deviceinfo.
127 lines
3.1 KiB
Go
127 lines
3.1 KiB
Go
// Copyright 2021 Clayton Craft <clayton@craftyguy.net>
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package deviceinfo
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
type DeviceInfo struct {
|
|
AppendDtb string
|
|
Arch string
|
|
BootimgAppendSEAndroidEnforce string
|
|
BootimgBlobpack string
|
|
BootimgDtbSecond string
|
|
BootimgMtkMkimage string
|
|
BootimgPxa string
|
|
BootimgQcdt string
|
|
Dtb string
|
|
FlashKernelOnUpdate string
|
|
FlashOffsetBase string
|
|
FlashOffsetKernel string
|
|
FlashOffsetRamdisk string
|
|
FlashOffsetSecond string
|
|
FlashOffsetTags string
|
|
FlashPagesize string
|
|
GenerateBootimg string
|
|
GenerateLegacyUbootInitfs string
|
|
InitfsCompression string
|
|
KernelCmdline string
|
|
LegacyUbootLoadAddress string
|
|
MesaDriver string
|
|
MkinitfsPostprocess string
|
|
ModulesInitfs string
|
|
}
|
|
|
|
func ReadDeviceinfo(file string) (DeviceInfo, error) {
|
|
var deviceinfo DeviceInfo
|
|
|
|
fd, err := os.Open(file)
|
|
if err != nil {
|
|
return deviceinfo, err
|
|
}
|
|
defer fd.Close()
|
|
|
|
if err := unmarshal(fd, &deviceinfo); err != nil {
|
|
return deviceinfo, err
|
|
}
|
|
|
|
return deviceinfo, nil
|
|
}
|
|
|
|
// Unmarshals a deviceinfo into a DeviceInfo struct
|
|
func unmarshal(r io.Reader, devinfo *DeviceInfo) error {
|
|
s := bufio.NewScanner(r)
|
|
for s.Scan() {
|
|
line := s.Text()
|
|
if strings.HasPrefix(line, "#") {
|
|
continue
|
|
}
|
|
|
|
// line isn't setting anything, so just ignore it
|
|
if !strings.Contains(line, "=") {
|
|
continue
|
|
}
|
|
|
|
// sometimes line has a comment at the end after setting an option
|
|
line = strings.SplitN(line, "#", 2)[0]
|
|
line = strings.TrimSpace(line)
|
|
|
|
// must support having '=' in the value (e.g. kernel cmdline)
|
|
parts := strings.SplitN(line, "=", 2)
|
|
if len(parts) != 2 {
|
|
return fmt.Errorf("error parsing deviceinfo line, invalid format: %s", line)
|
|
}
|
|
|
|
name, val := parts[0], parts[1]
|
|
val = strings.ReplaceAll(val, "\"", "")
|
|
|
|
if name == "deviceinfo_format_version" && val != "0" {
|
|
return fmt.Errorf("deviceinfo format version %q is not supported", val)
|
|
}
|
|
|
|
fieldName := nameToField(name)
|
|
|
|
if fieldName == "" {
|
|
return fmt.Errorf("error parsing deviceinfo line, invalid format: %s", line)
|
|
}
|
|
|
|
field := reflect.ValueOf(devinfo).Elem().FieldByName(fieldName)
|
|
if !field.IsValid() {
|
|
// an option that meets the deviceinfo "specification", but isn't
|
|
// one we care about in this module
|
|
continue
|
|
}
|
|
field.SetString(val)
|
|
}
|
|
if err := s.Err(); err != nil {
|
|
log.Print("unable to parse deviceinfo: ", err)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Convert string into the string format used for DeviceInfo fields.
|
|
// Note: does not test that the resulting field name is a valid field in the
|
|
// DeviceInfo struct!
|
|
func nameToField(name string) string {
|
|
var field string
|
|
parts := strings.Split(name, "_")
|
|
for _, p := range parts {
|
|
if p == "deviceinfo" {
|
|
continue
|
|
}
|
|
field = field + strings.Title(p)
|
|
}
|
|
|
|
return field
|
|
}
|