2014-03-23 02:51:22 +01:00
// Host detection.
2014-03-02 20:21:23 +01:00
package embd
2014-02-26 23:54:53 +01:00
import (
"fmt"
2014-09-09 16:57:27 +02:00
"io/ioutil"
2014-02-26 23:54:53 +01:00
"os/exec"
"strconv"
"strings"
)
2014-03-23 02:51:22 +01:00
// The Host type represents all the supported host types.
2014-03-23 22:34:58 +01:00
type Host string
2014-02-26 23:54:53 +01:00
const (
2014-03-23 02:51:22 +01:00
// HostNull reprents a null host.
2014-03-23 22:34:58 +01:00
HostNull Host = ""
2014-03-23 02:51:22 +01:00
// HostRPi represents the RaspberryPi.
2014-03-23 22:34:58 +01:00
HostRPi = "Raspberry Pi"
2014-03-23 02:51:22 +01:00
// HostBBB represents the BeagleBone Black.
2014-03-23 22:34:58 +01:00
HostBBB = "BeagleBone Black"
// HostGalileo represents the Intel Galileo board.
HostGalileo = "Intel Galileo"
2014-03-23 02:51:22 +01:00
// HostCubieTruck represents the Cubie Truck.
2014-03-23 22:34:58 +01:00
HostCubieTruck = "CubieTruck"
2014-03-23 02:51:22 +01:00
2014-05-21 23:26:50 +02:00
// HostRadxa represents the Radxa board.
2014-03-23 22:34:58 +01:00
HostRadxa = "Radxa"
2014-02-26 23:54:53 +01:00
)
func execOutput ( name string , arg ... string ) ( output string , err error ) {
var out [ ] byte
if out , err = exec . Command ( name , arg ... ) . Output ( ) ; err != nil {
return
}
2014-03-02 15:09:04 +01:00
output = strings . TrimSpace ( string ( out ) )
2014-02-26 23:54:53 +01:00
return
}
2014-03-01 21:24:01 +01:00
func parseVersion ( str string ) ( major , minor , patch int , err error ) {
2014-05-16 08:48:53 +02:00
versionNumber := strings . Split ( str , "-" )
parts := strings . Split ( versionNumber [ 0 ] , "." )
2014-03-01 21:24:01 +01:00
len := len ( parts )
2014-02-26 23:54:53 +01:00
if major , err = strconv . Atoi ( parts [ 0 ] ) ; err != nil {
2014-03-01 21:24:01 +01:00
return 0 , 0 , 0 , err
2014-02-26 23:54:53 +01:00
}
if minor , err = strconv . Atoi ( parts [ 1 ] ) ; err != nil {
2014-03-01 21:24:01 +01:00
return 0 , 0 , 0 , err
2014-02-26 23:54:53 +01:00
}
2014-03-01 21:24:01 +01:00
if len > 2 {
part := parts [ 2 ]
part = strings . TrimSuffix ( part , "+" )
if patch , err = strconv . Atoi ( part ) ; err != nil {
return 0 , 0 , 0 , err
}
2014-02-26 23:54:53 +01:00
}
2014-03-01 21:24:01 +01:00
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 )
2014-02-26 23:54:53 +01:00
}
2015-01-13 23:15:25 +01:00
func cpuInfo ( ) ( model , hardware string , revision int , err error ) {
output , err := ioutil . ReadFile ( "/proc/cpuinfo" )
2014-09-09 16:57:27 +02:00
if err != nil {
2015-01-13 23:15:25 +01:00
return "" , "" , 0 , err
2014-09-09 16:57:27 +02:00
}
2015-01-13 23:15:25 +01:00
for _ , line := range strings . Split ( string ( output ) , "\n" ) {
fields := strings . Split ( line , ":" )
if len ( fields ) < 1 {
continue
}
2015-01-15 02:06:01 +01:00
switch {
case strings . HasPrefix ( fields [ 0 ] , "Revision" ) :
revs := strings . TrimSpace ( fields [ 1 ] )
2015-02-17 12:34:09 +01:00
rev , err := strconv . ParseInt ( revs , 16 , 32 )
2015-01-13 23:15:25 +01:00
if err != nil {
continue
}
revision = int ( rev )
2015-01-15 02:06:01 +01:00
case strings . HasPrefix ( fields [ 0 ] , "Hardware" ) :
2015-01-13 23:15:25 +01:00
hardware = fields [ 1 ]
2015-01-15 02:06:01 +01:00
case strings . HasPrefix ( fields [ 0 ] , "model name" ) :
2015-01-13 23:15:25 +01:00
model = fields [ 1 ]
2014-09-09 16:57:27 +02:00
}
}
2015-01-13 23:15:25 +01:00
return model , hardware , revision , nil
2014-09-09 16:57:27 +02:00
}
2014-03-23 02:51:22 +01:00
// DetectHost returns the detected host and its revision number.
2015-01-13 23:15:25 +01:00
func DetectHost ( ) ( host Host , rev int , err error ) {
2014-02-26 23:54:53 +01:00
major , minor , patch , err := kernelVersion ( )
if err != nil {
2014-03-02 20:21:23 +01:00
return HostNull , 0 , err
2014-02-26 23:54:53 +01:00
}
if major < 3 || ( major == 3 && minor < 8 ) {
2014-03-23 11:18:09 +01:00
return HostNull , 0 , fmt . Errorf ( "embd: linux kernel versions lower than 3.8 are not supported. you have %v.%v.%v" , major , minor , patch )
2014-02-26 23:54:53 +01:00
}
2015-01-13 23:15:25 +01:00
model , hardware , rev , err := cpuInfo ( )
2014-02-26 23:54:53 +01:00
if err != nil {
2014-03-02 20:21:23 +01:00
return HostNull , 0 , err
2014-02-26 23:54:53 +01:00
}
2015-01-13 23:15:25 +01:00
switch {
case strings . Contains ( model , "ARMv7" ) && ( strings . Contains ( hardware , "AM33XX" ) || strings . Contains ( hardware , "AM335X" ) ) :
return HostBBB , rev , nil
2015-02-17 12:34:09 +01:00
case strings . Contains ( hardware , "BCM2708" ) || strings . Contains ( hardware , "BCM2709" ) :
2015-01-13 23:15:25 +01:00
return HostRPi , rev , nil
2014-02-26 23:54:53 +01:00
default :
2015-02-17 12:34:09 +01:00
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 )
2014-02-26 23:54:53 +01:00
}
}