/* * Copyright (c) Karan Misra 2014 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and * associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // 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" // HostEdison represents teh Intel Edison board. HostEdison = "Intel Edison" // 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 strings.Contains(model, "Genuine Intel(R) CPU 4000 @ 500MHz"): return HostEdison, 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/cfreeman/embd/issues`, host, model) } }