-
Notifications
You must be signed in to change notification settings - Fork 156
/
detect.go
139 lines (118 loc) · 3.46 KB
/
detect.go
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
137
138
139
// Host detection.
package embd
import (
"fmt"
"io/ioutil"
"os/exec"
"strconv"
"strings"
)
// The Host type represents all the supported host types.
type Host string
const (
// HostNull reprents a null host.
HostNull Host = ""
// HostRPi represents the RaspberryPi.
HostRPi = "Raspberry Pi"
// HostBBB represents the BeagleBone Black.
HostBBB = "BeagleBone Black"
// HostGalileo represents the Intel Galileo board.
HostGalileo = "Intel Galileo"
// HostCubieTruck represents the Cubie Truck.
HostCubieTruck = "CubieTruck"
// HostRadxa represents the Radxa board.
HostRadxa = "Radxa"
// HostCHIP represents the NextThing C.H.I.P.
HostCHIP = "CHIP"
)
func execOutput(name string, arg ...string) (output string, err error) {
var out []byte
if out, err = exec.Command(name, arg...).Output(); err != nil {
return
}
output = strings.TrimSpace(string(out))
return
}
func parseVersion(str string) (major, minor, patch int, err error) {
versionNumber := strings.Split(str, "-")
parts := strings.Split(versionNumber[0], ".")
len := len(parts)
if major, err = strconv.Atoi(parts[0]); err != nil {
return 0, 0, 0, err
}
if minor, err = strconv.Atoi(parts[1]); err != nil {
return 0, 0, 0, err
}
if len > 2 {
part := parts[2]
part = strings.TrimSuffix(part, "+")
if patch, err = strconv.Atoi(part); err != nil {
return 0, 0, 0, err
}
}
return major, minor, patch, err
}
func kernelVersion() (major, minor, patch int, err error) {
output, err := execOutput("uname", "-r")
if err != nil {
return 0, 0, 0, err
}
return parseVersion(output)
}
func cpuInfo() (model, hardware string, revision int, err error) {
output, err := ioutil.ReadFile("/proc/cpuinfo")
if err != nil {
return "", "", 0, err
}
for _, line := range strings.Split(string(output), "\n") {
fields := strings.Split(line, ":")
if len(fields) < 1 {
continue
}
switch {
case strings.HasPrefix(fields[0], "Revision"):
revs := strings.TrimSpace(fields[1])
rev, err := strconv.ParseInt(revs, 16, 32)
if err != nil {
continue
}
revision = int(rev)
case strings.HasPrefix(fields[0], "Hardware"):
hardware = strings.TrimSpace(fields[1])
case strings.HasPrefix(fields[0], "model name"):
model = fields[1]
}
}
return model, hardware, revision, nil
}
// DetectHost returns the detected host and its revision number.
func DetectHost() (host Host, rev int, err error) {
major, minor, patch, err := kernelVersion()
if err != nil {
return HostNull, 0, err
}
if major < 3 || (major == 3 && minor < 8) {
return HostNull, 0, fmt.Errorf(
"embd: linux kernel versions lower than 3.8 are not supported, "+
"you have %v.%v.%v", major, minor, patch)
}
model, hardware, rev, err := cpuInfo()
if err != nil {
return HostNull, 0, err
}
switch {
case strings.Contains(model, "ARMv7") && (strings.Contains(hardware, "AM33XX") || strings.Contains(hardware, "AM335X")):
return HostBBB, rev, nil
case strings.Contains(hardware, "BCM2708") || strings.Contains(hardware, "BCM2709") || strings.Contains(hardware, "BCM2835"):
return HostRPi, rev, nil
case hardware == "Allwinner sun4i/sun5i Families":
if major < 4 || (major == 4 && minor < 4) {
return HostNull, 0, fmt.Errorf(
"embd: linux kernel version 4.4+ required, you have %v.%v",
major, minor)
}
return HostCHIP, rev, nil
default:
return HostNull, 0, fmt.Errorf(`embd: your host "%v:%v" is not supported at this moment. request support at https://github.com/kidoman/embd/issues`, host, model)
}
}