http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/image/image.go ---------------------------------------------------------------------- diff --git a/newt/image/image.go b/newt/image/image.go deleted file mode 100644 index dd09b16..0000000 --- a/newt/image/image.go +++ /dev/null @@ -1,777 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package image - -import ( - "bytes" - "crypto" - "crypto/ecdsa" - "crypto/rand" - "crypto/rsa" - "crypto/sha256" - "crypto/x509" - "encoding/asn1" - "encoding/binary" - "encoding/hex" - "encoding/pem" - "fmt" - "io" - "io/ioutil" - "math/big" - "os" - "sort" - "strconv" - "strings" - - log "github.com/Sirupsen/logrus" - - "mynewt.apache.org/newt/newt/pkg" - "mynewt.apache.org/newt/util" -) - -type ImageVersion struct { - Major uint8 - Minor uint8 - Rev uint16 - BuildNum uint32 -} - -type Image struct { - SourceBin string - TargetImg string - Version ImageVersion - SigningRSA *rsa.PrivateKey - SigningEC *ecdsa.PrivateKey - KeyId uint8 - Hash []byte - SrcSkip uint // Number of bytes to skip from the source image. - HeaderSize uint // If non-zero pad out the header to this size. - TotalSize uint // Total size, in bytes, of the generated .img file. -} - -type ImageHdr struct { - Magic uint32 - TlvSz uint16 - KeyId uint8 - Pad1 uint8 - HdrSz uint16 - Pad2 uint16 - ImgSz uint32 - Flags uint32 - Vers ImageVersion - Pad3 uint32 -} - -type ImageTrailerTlv struct { - Type uint8 - Pad uint8 - Len uint16 -} - -const ( - IMAGE_MAGIC = 0x96f3b83c /* Image header magic */ -) - -const ( - IMAGE_HEADER_SIZE = 32 -) - -/* - * Image header flags. - */ -const ( - IMAGE_F_PIC = 0x00000001 - IMAGE_F_SHA256 = 0x00000002 /* Image contains hash TLV */ - IMAGE_F_PKCS15_RSA2048_SHA256 = 0x00000004 /* PKCS15 w/RSA2048 and SHA256 */ - IMAGE_F_ECDSA224_SHA256 = 0x00000008 /* ECDSA224 over SHA256 */ - IMAGE_F_NON_BOOTABLE = 0x00000010 /* non bootable image */ - IMAGE_F_ECDSA256_SHA256 = 0x00000020 /* ECDSA256 over SHA256 */ -) - -/* - * Image trailer TLV types. - */ -const ( - IMAGE_TLV_SHA256 = 1 - IMAGE_TLV_RSA2048 = 2 - IMAGE_TLV_ECDSA224 = 3 - IMAGE_TLV_ECDSA256 = 4 -) - -/* - * Data that's going to go to build manifest file - */ -type ImageManifestSizeArea struct { - Name string `json:"name"` - Size uint32 `json:"size"` -} - -type ImageManifestSizeSym struct { - Name string `json:"name"` - Areas []*ImageManifestSizeArea `json:"areas"` -} - -type ImageManifestSizeFile struct { - Name string `json:"name"` - Syms []*ImageManifestSizeSym `json:"sym"` -} - -type ImageManifestSizePkg struct { - Name string `json:"name"` - Files []*ImageManifestSizeFile `json:"files"` -} - -type ImageManifestSizeCollector struct { - Pkgs []*ImageManifestSizePkg -} - -type ImageManifest struct { - Name string `json:"name"` - Date string `json:"build_time"` - Version string `json:"build_version"` - BuildID string `json:"id"` - Image string `json:"image"` - ImageHash string `json:"image_hash"` - Loader string `json:"loader"` - LoaderHash string `json:"loader_hash"` - Pkgs []*ImageManifestPkg `json:"pkgs"` - LoaderPkgs []*ImageManifestPkg `json:"loader_pkgs,omitempty"` - TgtVars []string `json:"target"` - Repos []ImageManifestRepo `json:"repos"` - - PkgSizes []*ImageManifestSizePkg `json:"pkgsz"` - LoaderPkgSizes []*ImageManifestSizePkg `json:"loader_pkgsz,omitempty"` -} - -type ImageManifestPkg struct { - Name string `json:"name"` - Repo string `json:"repo"` -} - -type ImageManifestRepo struct { - Name string `json:"name"` - Commit string `json:"commit"` - Dirty bool `json:"dirty,omitempty"` - URL string `json:"url,omitempty"` -} - -type RepoManager struct { - repos map[string]ImageManifestRepo -} - -type ECDSASig struct { - R *big.Int - S *big.Int -} - -func ParseVersion(versStr string) (ImageVersion, error) { - var err error - var major uint64 - var minor uint64 - var rev uint64 - var buildNum uint64 - var ver ImageVersion - - components := strings.Split(versStr, ".") - major, err = strconv.ParseUint(components[0], 10, 8) - if err != nil { - return ver, util.FmtNewtError("Invalid version string %s", versStr) - } - if len(components) > 1 { - minor, err = strconv.ParseUint(components[1], 10, 8) - if err != nil { - return ver, util.FmtNewtError("Invalid version string %s", versStr) - } - } - if len(components) > 2 { - rev, err = strconv.ParseUint(components[2], 10, 16) - if err != nil { - return ver, util.FmtNewtError("Invalid version string %s", versStr) - } - } - if len(components) > 3 { - buildNum, err = strconv.ParseUint(components[3], 10, 32) - if err != nil { - return ver, util.FmtNewtError("Invalid version string %s", versStr) - } - } - - ver.Major = uint8(major) - ver.Minor = uint8(minor) - ver.Rev = uint16(rev) - ver.BuildNum = uint32(buildNum) - return ver, nil -} - -func (ver ImageVersion) String() string { - return fmt.Sprintf("%d.%d.%d.%d", - ver.Major, ver.Minor, ver.Rev, ver.BuildNum) -} - -func NewImage(srcBinPath string, dstImgPath string) (*Image, error) { - image := &Image{} - - image.SourceBin = srcBinPath - image.TargetImg = dstImgPath - return image, nil -} - -func (image *Image) SetVersion(versStr string) error { - ver, err := ParseVersion(versStr) - if err != nil { - return err - } - - log.Debugf("Assigning version number %d.%d.%d.%d\n", - ver.Major, ver.Minor, ver.Rev, ver.BuildNum) - - image.Version = ver - - buf := new(bytes.Buffer) - err = binary.Write(buf, binary.LittleEndian, image.Version) - if err != nil { - fmt.Printf("Bombing out\n") - return nil - } - - return nil -} - -func (image *Image) SetSigningKey(fileName string, keyId uint8) error { - data, err := ioutil.ReadFile(fileName) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Error reading key file: %s", err)) - } - - block, data := pem.Decode(data) - if block != nil && block.Type == "EC PARAMETERS" { - /* - * Openssl prepends an EC PARAMETERS block before the - * key itself. If we see this first, just skip it, - * and go on to the data block. - */ - block, _ = pem.Decode(data) - } - if block != nil && block.Type == "RSA PRIVATE KEY" { - /* - * ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 - * PKCS#1 DER encoded form. - */ - privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Private key parsing "+ - "failed: %s", err)) - } - image.SigningRSA = privateKey - } - if block != nil && block.Type == "EC PRIVATE KEY" { - /* - * ParseECPrivateKey returns a EC private key - */ - privateKey, err := x509.ParseECPrivateKey(block.Bytes) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Private key parsing "+ - "failed: %s", err)) - } - image.SigningEC = privateKey - } - if image.SigningEC == nil && image.SigningRSA == nil { - return util.NewNewtError("Unknown private key format, EC/RSA private " + - "key in PEM format only.") - } - image.KeyId = keyId - - return nil -} - -func (image *Image) sigHdrType() (uint32, error) { - if image.SigningRSA != nil { - return IMAGE_F_PKCS15_RSA2048_SHA256, nil - } else if image.SigningEC != nil { - switch image.SigningEC.Curve.Params().Name { - case "P-224": - return IMAGE_F_ECDSA224_SHA256, nil - case "P-256": - return IMAGE_F_ECDSA256_SHA256, nil - default: - return 0, util.NewNewtError("Unsupported ECC curve") - } - } else { - return 0, nil - } -} - -func (image *Image) sigLen() uint16 { - if image.SigningRSA != nil { - return 256 - } else if image.SigningEC != nil { - switch image.SigningEC.Curve.Params().Name { - case "P-224": - return 68 - case "P-256": - return 72 - default: - return 0 - } - } else { - return 0 - } -} - -func (image *Image) sigTlvType() uint8 { - if image.SigningRSA != nil { - return IMAGE_TLV_RSA2048 - } else if image.SigningEC != nil { - switch image.SigningEC.Curve.Params().Name { - case "P-224": - return IMAGE_TLV_ECDSA224 - case "P-256": - return IMAGE_TLV_ECDSA256 - default: - return 0 - } - } else { - return 0 - } -} - -func (image *Image) Generate(loader *Image) error { - binFile, err := os.Open(image.SourceBin) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Can't open app binary: %s", - err.Error())) - } - defer binFile.Close() - - binInfo, err := binFile.Stat() - if err != nil { - return util.NewNewtError(fmt.Sprintf("Can't stat app binary %s: %s", - image.SourceBin, err.Error())) - } - - imgFile, err := os.OpenFile(image.TargetImg, - os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Can't open target image %s: %s", - image.TargetImg, err.Error())) - } - defer imgFile.Close() - - /* - * Compute hash while updating the file. - */ - hash := sha256.New() - - if loader != nil { - err = binary.Write(hash, binary.LittleEndian, loader.Hash) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to seed hash: %s", - err.Error())) - } - } - - /* - * First the header - */ - hdr := &ImageHdr{ - Magic: IMAGE_MAGIC, - TlvSz: 0, - KeyId: 0, - Pad1: 0, - HdrSz: IMAGE_HEADER_SIZE, - Pad2: 0, - ImgSz: uint32(binInfo.Size()) - uint32(image.SrcSkip), - Flags: 0, - Vers: image.Version, - Pad3: 0, - } - - hdr.Flags, err = image.sigHdrType() - if err != nil { - return err - } - if hdr.Flags != 0 { - /* - * Signature present - */ - hdr.TlvSz = 4 + image.sigLen() - hdr.KeyId = image.KeyId - } - - hdr.TlvSz += 4 + 32 - hdr.Flags |= IMAGE_F_SHA256 - - if loader != nil { - hdr.Flags |= IMAGE_F_NON_BOOTABLE - } - - if image.HeaderSize != 0 { - /* - * Pad the header out to the given size. There will - * just be zeros between the header and the start of - * the image when it is padded. - */ - if image.HeaderSize < IMAGE_HEADER_SIZE { - return util.NewNewtError(fmt.Sprintf("Image header must be at least %d bytes", IMAGE_HEADER_SIZE)) - } - - hdr.HdrSz = uint16(image.HeaderSize) - } - - err = binary.Write(imgFile, binary.LittleEndian, hdr) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to serialize image hdr: %s", - err.Error())) - } - err = binary.Write(hash, binary.LittleEndian, hdr) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to hash data: %s", - err.Error())) - } - - if image.HeaderSize > IMAGE_HEADER_SIZE { - /* - * Pad the image (and hash) with zero bytes to fill - * out the buffer. - */ - buf := make([]byte, image.HeaderSize-IMAGE_HEADER_SIZE) - - _, err = imgFile.Write(buf) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to write padding: %s", - err.Error())) - } - - _, err = hash.Write(buf) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to hash padding: %s", - err.Error())) - } - } - - /* - * Skip requested initial part of image. - */ - if image.SrcSkip > 0 { - buf := make([]byte, image.SrcSkip) - _, err = binFile.Read(buf) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to read from %s: %s", - image.SourceBin, err.Error())) - } - - nonZero := false - for _, b := range buf { - if b != 0 { - nonZero = true - break - } - } - if nonZero { - log.Warnf("Skip requested of iamge %s, but image not preceeded by %d bytes of all zeros", - image.SourceBin, image.SrcSkip) - } - } - - /* - * Followed by data. - */ - dataBuf := make([]byte, 1024) - for { - cnt, err := binFile.Read(dataBuf) - if err != nil && err != io.EOF { - return util.NewNewtError(fmt.Sprintf("Failed to read from %s: %s", - image.SourceBin, err.Error())) - } - if cnt == 0 { - break - } - _, err = imgFile.Write(dataBuf[0:cnt]) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to write to %s: %s", - image.TargetImg, err.Error())) - } - _, err = hash.Write(dataBuf[0:cnt]) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to hash data: %s", - err.Error())) - } - } - - image.Hash = hash.Sum(nil) - - /* - * Trailer with hash of the data - */ - tlv := &ImageTrailerTlv{ - Type: IMAGE_TLV_SHA256, - Pad: 0, - Len: uint16(len(image.Hash)), - } - err = binary.Write(imgFile, binary.LittleEndian, tlv) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+ - "trailer: %s", err.Error())) - } - _, err = imgFile.Write(image.Hash) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to append hash: %s", - err.Error())) - } - - if image.SigningRSA != nil { - /* - * If signing key was set, generate TLV for that. - */ - tlv := &ImageTrailerTlv{ - Type: IMAGE_TLV_RSA2048, - Pad: 0, - Len: 256, /* 2048 bits */ - } - signature, err := rsa.SignPKCS1v15(rand.Reader, image.SigningRSA, - crypto.SHA256, image.Hash) - if err != nil { - return util.NewNewtError(fmt.Sprintf( - "Failed to compute signature: %s", err)) - } - - err = binary.Write(imgFile, binary.LittleEndian, tlv) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+ - "trailer: %s", err.Error())) - } - _, err = imgFile.Write(signature) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to append sig: %s", - err.Error())) - } - } - if image.SigningEC != nil { - r, s, err := ecdsa.Sign(rand.Reader, image.SigningEC, image.Hash) - if err != nil { - return util.NewNewtError(fmt.Sprintf( - "Failed to compute signature: %s", err)) - } - - sigLen := image.sigLen() - - var ECDSA ECDSASig - ECDSA.R = r - ECDSA.S = s - signature, err := asn1.Marshal(ECDSA) - if err != nil { - return util.NewNewtError(fmt.Sprintf( - "Failed to construct signature: %s", err)) - } - if len(signature) > int(sigLen) { - return util.NewNewtError(fmt.Sprintf( - "Something is really wrong\n")) - } - tlv := &ImageTrailerTlv{ - Type: image.sigTlvType(), - Pad: 0, - Len: sigLen, - } - err = binary.Write(imgFile, binary.LittleEndian, tlv) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+ - "trailer: %s", err.Error())) - } - _, err = imgFile.Write(signature) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to append sig: %s", - err.Error())) - } - pad := make([]byte, int(sigLen)-len(signature)) - _, err = imgFile.Write(pad) - if err != nil { - return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+ - "trailer: %s", err.Error())) - } - } - - util.StatusMessage(util.VERBOSITY_VERBOSE, - "Computed Hash for image %s as %s \n", - image.TargetImg, hex.EncodeToString(image.Hash)) - - sz, err := imgFile.Seek(0, io.SeekCurrent) - if err != nil { - return util.FmtNewtError("Failed to calculate file size of generated "+ - "image %s: %s", image.TargetImg, err.Error()) - } - image.TotalSize = uint(sz) - - return nil -} - -func CreateBuildId(app *Image, loader *Image) []byte { - return app.Hash -} - -func NewRepoManager() *RepoManager { - return &RepoManager{ - repos: make(map[string]ImageManifestRepo), - } -} - -func (r *RepoManager) GetImageManifestPkg( - lpkg *pkg.LocalPackage) *ImageManifestPkg { - - ip := &ImageManifestPkg{ - Name: lpkg.Name(), - } - - var path string - if lpkg.Repo().IsLocal() { - ip.Repo = lpkg.Repo().Name() - path = lpkg.BasePath() - } else { - ip.Repo = lpkg.Repo().Name() - path = lpkg.BasePath() - } - - if _, present := r.repos[ip.Repo]; present { - return ip - } - - repo := ImageManifestRepo{ - Name: ip.Repo, - } - - // Make sure we restore the current working dir to whatever it was when - // this function was called - cwd, err := os.Getwd() - if err != nil { - log.Debugf("Unable to determine current working directory: %v", err) - return ip - } - defer os.Chdir(cwd) - - if err := os.Chdir(path); err != nil { - return ip - } - - var res []byte - - res, err = util.ShellCommand([]string{ - "git", - "rev-parse", - "HEAD", - }, nil) - if err != nil { - log.Debugf("Unable to determine commit hash for %s: %v", path, err) - repo.Commit = "UNKNOWN" - } else { - repo.Commit = strings.TrimSpace(string(res)) - res, err = util.ShellCommand([]string{ - "git", - "status", - "--porcelain", - }, nil) - if err != nil { - log.Debugf("Unable to determine dirty state for %s: %v", path, err) - } else { - if len(res) > 0 { - repo.Dirty = true - } - } - res, err = util.ShellCommand([]string{ - "git", - "config", - "--get", - "remote.origin.url", - }, nil) - if err != nil { - log.Debugf("Unable to determine URL for %s: %v", path, err) - } else { - repo.URL = strings.TrimSpace(string(res)) - } - } - r.repos[ip.Repo] = repo - - return ip -} - -func (r *RepoManager) AllRepos() []ImageManifestRepo { - keys := make([]string, 0, len(r.repos)) - for k := range r.repos { - keys = append(keys, k) - } - - sort.Strings(keys) - - repos := make([]ImageManifestRepo, 0, len(keys)) - for _, key := range keys { - repos = append(repos, r.repos[key]) - } - - return repos -} - -func NewImageManifestSizeCollector() *ImageManifestSizeCollector { - return &ImageManifestSizeCollector{} -} - -func (c *ImageManifestSizeCollector) AddPkg(pkg string) *ImageManifestSizePkg { - p := &ImageManifestSizePkg{ - Name: pkg, - } - c.Pkgs = append(c.Pkgs, p) - - return p -} - -func (c *ImageManifestSizePkg) AddSymbol(file string, sym string, area string, - symSz uint32) { - f := c.addFile(file) - s := f.addSym(sym) - s.addArea(area, symSz) -} - -func (p *ImageManifestSizePkg) addFile(file string) *ImageManifestSizeFile { - for _, f := range p.Files { - if f.Name == file { - return f - } - } - f := &ImageManifestSizeFile{ - Name: file, - } - p.Files = append(p.Files, f) - - return f -} - -func (f *ImageManifestSizeFile) addSym(sym string) *ImageManifestSizeSym { - s := &ImageManifestSizeSym{ - Name: sym, - } - f.Syms = append(f.Syms, s) - - return s -} - -func (s *ImageManifestSizeSym) addArea(area string, areaSz uint32) { - a := &ImageManifestSizeArea{ - Name: area, - Size: areaSz, - } - s.Areas = append(s.Areas, a) -}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/interfaces/interfaces.go ---------------------------------------------------------------------- diff --git a/newt/interfaces/interfaces.go b/newt/interfaces/interfaces.go deleted file mode 100644 index c12b58b..0000000 --- a/newt/interfaces/interfaces.go +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package interfaces - -type PackageInterface interface { - Name() string - FullName() string - BasePath() string - Repo() RepoInterface - Type() PackageType -} - -type PackageType int - -type RepoInterface interface { - Name() string - IsLocal() bool - Path() string -} - -type VersionReqInterface interface { - CompareType() string - Version() VersionInterface - String() string -} - -type VersionInterface interface { - SatisfiesVersion(versReq []VersionReqInterface) bool - CompareVersions(vers1 VersionInterface, vers2 VersionInterface) int64 - Major() int64 - Minor() int64 - Revision() int64 - Stability() string - String() string -} - -type PackageList map[string]*map[string]PackageInterface - -type DependencyInterface interface { - SatisfiesDependency(pkg PackageInterface) bool - String() string -} - -type ProjectInterface interface { - Name() string - Path() string - ResolveDependency(dep DependencyInterface) PackageInterface - ResolvePath(basePath string, name string) (string, error) - PackageList() PackageList - FindRepoPath(rname string) string -} - -var globalProject ProjectInterface - -func GetProject() ProjectInterface { - return globalProject -} - -func SetProject(proj ProjectInterface) { - globalProject = proj -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/mfg/create.go ---------------------------------------------------------------------- diff --git a/newt/mfg/create.go b/newt/mfg/create.go deleted file mode 100644 index 08614e0..0000000 --- a/newt/mfg/create.go +++ /dev/null @@ -1,515 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package mfg - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sort" - "time" - - "mynewt.apache.org/newt/newt/builder" - "mynewt.apache.org/newt/newt/flash" - "mynewt.apache.org/newt/newt/pkg" - "mynewt.apache.org/newt/newt/target" - "mynewt.apache.org/newt/util" -) - -type mfgManifest struct { - BuildTime string `json:"build_time"` - MfgHash string `json:"mfg_hash"` - Version string `json:"version"` - MetaSection int `json:"meta_section"` - MetaOffset int `json:"meta_offset"` -} - -type createState struct { - // {0:[section0blob], 1:[section1blob], ...} - dsMap map[int][]byte - metaOffset int - hashOffset int - hash []byte -} - -func insertPartIntoBlob(blob []byte, part mfgPart) { - partEnd := part.offset + len(part.data) - - if len(blob) < partEnd { - panic("internal error; mfg blob too small") - } - - copy(blob[part.offset:partEnd], part.data) -} - -func (mi *MfgImage) partFromImage( - imgPath string, flashAreaName string) (mfgPart, error) { - - part := mfgPart{ - // Boot loader and images always go in device 0. - device: 0, - } - - area, ok := mi.bsp.FlashMap.Areas[flashAreaName] - if !ok { - return part, util.FmtNewtError( - "Image at \"%s\" requires undefined flash area \"%s\"", - imgPath, flashAreaName) - } - - part.name = fmt.Sprintf("%s (%s)", flashAreaName, filepath.Base(imgPath)) - part.offset = area.Offset - - var err error - - part.data, err = ioutil.ReadFile(imgPath) - if err != nil { - return part, util.ChildNewtError(err) - } - - overflow := len(part.data) - area.Size - if overflow > 0 { - return part, util.FmtNewtError( - "Image \"%s\" is too large to fit in flash area \"%s\"; "+ - "image-size=%d flash-area-size=%d overflow=%d", - imgPath, flashAreaName, len(part.data), area.Size, overflow) - } - - // If an image slot is used, the entire flash area is unwritable. This - // restriction comes from the boot loader's need to write status at the end - // of an area. Pad out part with unwriten flash (0xff). This probably - // isn't terribly efficient... - for i := 0; i < -overflow; i++ { - part.data = append(part.data, 0xff) - } - - return part, nil -} - -func partFromRawEntry(entry MfgRawEntry, entryIdx int) mfgPart { - return mfgPart{ - name: fmt.Sprintf("entry-%d (%s)", entryIdx, entry.filename), - offset: entry.offset, - data: entry.data, - } -} - -func (mi *MfgImage) targetParts() ([]mfgPart, error) { - parts := []mfgPart{} - - bootPath := mi.dstBootBinPath() - if bootPath != "" { - bootPart, err := mi.partFromImage( - bootPath, flash.FLASH_AREA_NAME_BOOTLOADER) - if err != nil { - return nil, err - } - - parts = append(parts, bootPart) - } - - for i := 0; i < 2; i++ { - imgPath := mi.dstImgPath(i) - if imgPath != "" { - areaName, err := areaNameFromImgIdx(i) - if err != nil { - return nil, err - } - - part, err := mi.partFromImage(imgPath, areaName) - if err != nil { - return nil, err - } - parts = append(parts, part) - } - } - - return parts, nil -} - -func sectionSize(parts []mfgPart) int { - greatest := 0 - - for _, part := range parts { - end := part.offset + len(part.data) - greatest = util.IntMax(greatest, end) - } - - return greatest -} - -func sectionFromParts(parts []mfgPart) []byte { - sectionSize := sectionSize(parts) - section := make([]byte, sectionSize) - - // Initialize section 0's data as unwritten flash (0xff). - for i, _ := range section { - section[i] = 0xff - } - - for _, part := range parts { - insertPartIntoBlob(section, part) - } - - return section -} - -func (mi *MfgImage) devicePartMap() (map[int][]mfgPart, error) { - dpMap := map[int][]mfgPart{} - - // Create parts from the raw entries. - for i, entry := range mi.rawEntries { - part := partFromRawEntry(entry, i) - dpMap[entry.device] = append(dpMap[entry.device], part) - } - - // Insert the boot loader and image parts into section 0. - targetParts, err := mi.targetParts() - if err != nil { - return nil, err - } - dpMap[0] = append(dpMap[0], targetParts...) - - // Sort each part slice by offset. - for device, _ := range dpMap { - sortParts(dpMap[device]) - } - - return dpMap, nil -} - -func (mi *MfgImage) deviceSectionMap() (map[int][]byte, error) { - dpMap, err := mi.devicePartMap() - if err != nil { - return nil, err - } - - // Convert each part slice into a section (byte slice). - dsMap := map[int][]byte{} - for device, parts := range dpMap { - dsMap[device] = sectionFromParts(parts) - } - - return dsMap, nil -} - -func (mi *MfgImage) createSections() (createState, error) { - cs := createState{} - - var err error - - if err := mi.detectOverlaps(); err != nil { - return cs, err - } - - cs.dsMap, err = mi.deviceSectionMap() - if err != nil { - return cs, err - } - - if cs.dsMap[0] == nil { - panic("Invalid state; no section 0") - } - - cs.metaOffset, cs.hashOffset, err = insertMeta(cs.dsMap[0], - mi.bsp.FlashMap) - if err != nil { - return cs, err - } - - // Calculate manufacturing hash. - devices := make([]int, 0, len(cs.dsMap)) - for device, _ := range cs.dsMap { - devices = append(devices, device) - } - sort.Ints(devices) - - sections := make([][]byte, len(devices)) - for i, device := range devices { - sections[i] = cs.dsMap[device] - } - cs.hash = calcMetaHash(sections) - copy(cs.dsMap[0][cs.hashOffset:cs.hashOffset+META_HASH_SZ], cs.hash) - - return cs, nil -} - -func areaNameFromImgIdx(imgIdx int) (string, error) { - switch imgIdx { - case 0: - return flash.FLASH_AREA_NAME_IMAGE_0, nil - case 1: - return flash.FLASH_AREA_NAME_IMAGE_1, nil - default: - return "", util.FmtNewtError("invalid image index: %d", imgIdx) - } -} - -func bootLoaderFromPaths(t *target.Target) []string { - return []string{ - /* boot.elf */ - builder.AppElfPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()), - - /* boot.elf.bin */ - builder.AppBinPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()), - - /* manifest.json */ - builder.ManifestPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()), - } -} - -func loaderFromPaths(t *target.Target) []string { - if t.LoaderName == "" { - return nil - } - - return []string{ - /* <loader>.elf */ - builder.AppElfPath(t.Name(), builder.BUILD_NAME_LOADER, - t.Loader().Name()), - - /* <app>.img */ - builder.AppImgPath(t.Name(), builder.BUILD_NAME_LOADER, - t.Loader().Name()), - } -} - -func appFromPaths(t *target.Target) []string { - return []string{ - /* <app>.elf */ - builder.AppElfPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()), - - /* <app>.img */ - builder.AppImgPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()), - - /* manifest.json */ - builder.ManifestPath(t.Name(), builder.BUILD_NAME_APP, t.App().Name()), - } -} - -func imageFromPaths(t *target.Target) []string { - paths := loaderFromPaths(t) - paths = append(paths, appFromPaths(t)...) - return paths -} - -func (mi *MfgImage) copyBinFile(srcPath string, dstDir string) error { - dstPath := dstDir + "/" + filepath.Base(srcPath) - - util.StatusMessage(util.VERBOSITY_VERBOSE, "copying file %s --> %s\n", - srcPath, dstPath) - - if err := util.CopyFile(srcPath, dstPath); err != nil { - return err - } - - return nil -} - -func (mi *MfgImage) copyBinFiles() error { - dstPath := MfgBinDir(mi.basePkg.Name()) - if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil { - return util.ChildNewtError(err) - } - - bootPaths := bootLoaderFromPaths(mi.boot) - for _, path := range bootPaths { - dstDir := MfgBootDir(mi.basePkg.Name()) - if err := mi.copyBinFile(path, dstDir); err != nil { - return err - } - } - - for i, imgTarget := range mi.images { - imgPaths := imageFromPaths(imgTarget) - dstDir := MfgImageBinDir(mi.basePkg.Name(), i) - for _, path := range imgPaths { - if err := mi.copyBinFile(path, dstDir); err != nil { - return err - } - } - } - - return nil -} - -func (mi *MfgImage) dstBootBinPath() string { - if mi.boot == nil { - return "" - } - - return fmt.Sprintf("%s/%s.elf.bin", - MfgBootDir(mi.basePkg.Name()), - pkg.ShortName(mi.boot.App())) -} - -func (mi *MfgImage) dstImgPath(slotIdx int) string { - var pack *pkg.LocalPackage - var imgIdx int - - if len(mi.images) >= 1 { - switch slotIdx { - case 0: - if mi.images[0].LoaderName != "" { - pack = mi.images[0].Loader() - } else { - pack = mi.images[0].App() - } - imgIdx = 0 - - case 1: - if mi.images[0].LoaderName != "" { - pack = mi.images[0].App() - imgIdx = 0 - } else { - if len(mi.images) >= 2 { - pack = mi.images[1].App() - } - imgIdx = 1 - } - - default: - panic(fmt.Sprintf("invalid image index: %d", imgIdx)) - } - } - - if pack == nil { - return "" - } - - return fmt.Sprintf("%s/%s.img", - MfgImageBinDir(mi.basePkg.Name(), imgIdx), pkg.ShortName(pack)) -} - -// Returns a slice containing the path of each file required to build the -// manufacturing image. -func (mi *MfgImage) FromPaths() []string { - paths := []string{} - - if mi.boot != nil { - paths = append(paths, bootLoaderFromPaths(mi.boot)...) - } - if len(mi.images) >= 1 { - paths = append(paths, imageFromPaths(mi.images[0])...) - } - if len(mi.images) >= 2 { - paths = append(paths, imageFromPaths(mi.images[1])...) - } - - for _, raw := range mi.rawEntries { - paths = append(paths, raw.filename) - } - - return paths -} - -func (mi *MfgImage) build() (createState, error) { - if err := mi.copyBinFiles(); err != nil { - return createState{}, err - } - - cs, err := mi.createSections() - if err != nil { - return cs, err - } - - return cs, nil -} - -func (mi *MfgImage) createManifest(cs createState) ([]byte, error) { - manifest := mfgManifest{ - BuildTime: time.Now().Format(time.RFC3339), - Version: mi.version.String(), - MfgHash: fmt.Sprintf("%x", cs.hash), - MetaSection: 0, - MetaOffset: cs.metaOffset, - } - buffer, err := json.MarshalIndent(manifest, "", " ") - if err != nil { - return nil, util.FmtNewtError("Failed to encode mfg manifest: %s", - err.Error()) - } - - return buffer, nil -} - -func appendNonEmptyStr(dst []string, src string) []string { - if src != "" { - dst = append(dst, src) - } - - return dst -} - -func (mi *MfgImage) ToPaths() []string { - paths := []string{} - - paths = appendNonEmptyStr(paths, mi.BootBinPath()) - paths = appendNonEmptyStr(paths, mi.BootElfPath()) - paths = appendNonEmptyStr(paths, mi.BootManifestPath()) - - for i := 0; i < len(mi.images); i++ { - paths = appendNonEmptyStr(paths, mi.LoaderImgPath(i)) - paths = appendNonEmptyStr(paths, mi.LoaderElfPath(i)) - paths = appendNonEmptyStr(paths, mi.AppImgPath(i)) - paths = appendNonEmptyStr(paths, mi.AppElfPath(i)) - paths = appendNonEmptyStr(paths, mi.ImageManifestPath(i)) - } - - paths = append(paths, mi.SectionBinPaths()...) - paths = append(paths, mi.ManifestPath()) - - return paths -} - -// @return [paths-of-artifacts], error -func (mi *MfgImage) CreateMfgImage() ([]string, error) { - cs, err := mi.build() - if err != nil { - return nil, err - } - - sectionDir := MfgSectionBinDir(mi.basePkg.Name()) - if err := os.MkdirAll(sectionDir, 0755); err != nil { - return nil, util.ChildNewtError(err) - } - - for device, section := range cs.dsMap { - sectionPath := MfgSectionBinPath(mi.basePkg.Name(), device) - if err := ioutil.WriteFile(sectionPath, section, 0644); err != nil { - return nil, util.ChildNewtError(err) - } - } - - manifest, err := mi.createManifest(cs) - if err != nil { - return nil, err - } - - manifestPath := mi.ManifestPath() - if err := ioutil.WriteFile(manifestPath, manifest, 0644); err != nil { - return nil, util.FmtNewtError("Failed to write mfg manifest file: %s", - err.Error()) - } - - return mi.ToPaths(), nil -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/mfg/load.go ---------------------------------------------------------------------- diff --git a/newt/mfg/load.go b/newt/mfg/load.go deleted file mode 100644 index 4370cda..0000000 --- a/newt/mfg/load.go +++ /dev/null @@ -1,305 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package mfg - -import ( - "fmt" - "io/ioutil" - "sort" - "strconv" - "strings" - - "github.com/spf13/cast" - - "mynewt.apache.org/newt/newt/pkg" - "mynewt.apache.org/newt/newt/project" - "mynewt.apache.org/newt/newt/target" - "mynewt.apache.org/newt/util" -) - -const MFG_YAML_FILENAME string = "mfg.yml" - -type partSorter struct { - parts []mfgPart -} - -func (s partSorter) Len() int { - return len(s.parts) -} -func (s partSorter) Swap(i, j int) { - s.parts[i], s.parts[j] = s.parts[j], s.parts[i] -} -func (s partSorter) Less(i, j int) bool { - return s.parts[i].offset < s.parts[j].offset -} - -func sortParts(parts []mfgPart) []mfgPart { - sorter := partSorter{ - parts: parts, - } - - sort.Sort(sorter) - return sorter.parts -} - -func (mi *MfgImage) loadError( - msg string, args ...interface{}) *util.NewtError { - - return util.FmtNewtError("Error in %s mfg: %s", mi.basePkg.Name(), - fmt.Sprintf(msg, args...)) - -} - -func (mi *MfgImage) loadTarget(targetName string) ( - *target.Target, error) { - - tgt := target.GetTargets()[targetName] - if tgt == nil { - return nil, mi.loadError("cannot resolve referenced target \"%s\"", - targetName) - } - - return tgt, nil -} - -func (mi *MfgImage) loadRawEntry( - entryIdx int, rawEntry map[string]string) (MfgRawEntry, error) { - - raw := MfgRawEntry{} - - var err error - - deviceStr := rawEntry["device"] - if deviceStr == "" { - return raw, mi.loadError( - "raw entry %d missing required \"device\" field", entryIdx) - } - - raw.device, err = util.AtoiNoOct(deviceStr) - if err != nil { - return raw, mi.loadError( - "raw entry %d contains invalid offset: %s", entryIdx, deviceStr) - } - - offsetStr := rawEntry["offset"] - if offsetStr == "" { - return raw, mi.loadError( - "raw entry %d missing required \"offset\" field", entryIdx) - } - - raw.offset, err = util.AtoiNoOct(offsetStr) - if err != nil { - return raw, mi.loadError( - "raw entry %d contains invalid offset: %s", entryIdx, offsetStr) - } - - raw.filename = rawEntry["file"] - if raw.filename == "" { - return raw, mi.loadError( - "raw entry %d missing required \"file\" field", entryIdx) - } - - if !strings.HasPrefix(raw.filename, "/") { - raw.filename = mi.basePkg.BasePath() + "/" + raw.filename - } - - raw.data, err = ioutil.ReadFile(raw.filename) - if err != nil { - return raw, mi.loadError( - "error loading file for raw entry %d; filename=%s: %s", - entryIdx, raw.filename, err.Error()) - } - - return raw, nil -} - -func (mi *MfgImage) detectInvalidDevices() error { - sectionIds := mi.sectionIds() - deviceIds := mi.bsp.FlashMap.DeviceIds() - - deviceMap := map[int]struct{}{} - for _, device := range deviceIds { - deviceMap[device] = struct{}{} - } - - invalidIds := []int{} - for _, sectionId := range sectionIds { - if _, ok := deviceMap[sectionId]; !ok { - invalidIds = append(invalidIds, sectionId) - } - } - - if len(invalidIds) == 0 { - return nil - } - - listStr := "" - for i, id := range invalidIds { - if i != 0 { - listStr += ", " - } - listStr += strconv.Itoa(id) - } - - return util.FmtNewtError( - "image specifies flash devices that are not present in the BSP's "+ - "flash map: %s", listStr) -} - -func (mi *MfgImage) detectOverlaps() error { - type overlap struct { - part0 mfgPart - part1 mfgPart - } - - overlaps := []overlap{} - - dpMap, err := mi.devicePartMap() - if err != nil { - return err - } - - // Iterate flash devices in order. - devices := make([]int, 0, len(dpMap)) - for device, _ := range dpMap { - devices = append(devices, device) - } - sort.Ints(devices) - - for _, device := range devices { - parts := dpMap[device] - for i, part0 := range parts[:len(parts)-1] { - part0End := part0.offset + len(part0.data) - for _, part1 := range parts[i+1:] { - // Parts are sorted by offset, so only one comparison is - // necessary to detect overlap. - if part1.offset < part0End { - overlaps = append(overlaps, overlap{ - part0: part0, - part1: part1, - }) - } - } - } - } - - if len(overlaps) > 0 { - str := "flash overlaps detected:" - for _, overlap := range overlaps { - - part0End := overlap.part0.offset + len(overlap.part0.data) - part1End := overlap.part1.offset + len(overlap.part1.data) - str += fmt.Sprintf("\n * s%d [%s] (%d - %d) <=> [%s] (%d - %d)", - overlap.part0.device, - overlap.part0.name, overlap.part0.offset, part0End, - overlap.part1.name, overlap.part1.offset, part1End) - } - - return util.NewNewtError(str) - } - - return nil -} - -func Load(basePkg *pkg.LocalPackage) (*MfgImage, error) { - v, err := util.ReadConfig(basePkg.BasePath(), - strings.TrimSuffix(MFG_YAML_FILENAME, ".yml")) - if err != nil { - return nil, err - } - - mi := &MfgImage{ - basePkg: basePkg, - } - - bootName := v.GetString("mfg.bootloader") - if bootName == "" { - return nil, mi.loadError("mfg.bootloader field required") - } - mi.boot, err = mi.loadTarget(bootName) - if err != nil { - return nil, err - } - - imgNames := v.GetStringSlice("mfg.images") - if imgNames != nil { - for _, imgName := range imgNames { - imgTarget, err := mi.loadTarget(imgName) - if err != nil { - return nil, err - } - - mi.images = append(mi.images, imgTarget) - } - } - - if len(mi.images) > 2 { - return nil, mi.loadError("too many images (%d); maximum is 2", - len(mi.images)) - } - - itf := v.Get("mfg.raw") - slice := cast.ToSlice(itf) - if slice != nil { - for i, entryItf := range slice { - yamlEntry := cast.ToStringMapString(entryItf) - entry, err := mi.loadRawEntry(i, yamlEntry) - if err != nil { - return nil, err - } - - mi.rawEntries = append(mi.rawEntries, entry) - } - } - - proj := project.GetProject() - - bspLpkg, err := proj.ResolvePackage(mi.basePkg.Repo(), - mi.boot.BspName) - if err != nil { - return nil, mi.loadError( - "could not resolve boot loader BSP package: %s", - mi.boot.BspName) - } - mi.bsp, err = pkg.NewBspPackage(bspLpkg) - if err != nil { - return nil, mi.loadError(err.Error()) - } - - for _, imgTarget := range mi.images { - if len(mi.images) > 1 && imgTarget.LoaderName != "" { - return nil, mi.loadError("only one image allowed in "+ - "split image mode (%s is a split build)", imgTarget.Name()) - } - - if imgTarget.Bsp() != mi.bsp.LocalPackage { - return nil, mi.loadError( - "image target \"%s\" specified conflicting BSP; "+ - "boot loader uses %s, image uses %s", - imgTarget.Name(), mi.bsp.Name(), imgTarget.BspName) - } - } - - if err := mi.detectInvalidDevices(); err != nil { - return nil, err - } - - return mi, nil -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/mfg/meta.go ---------------------------------------------------------------------- diff --git a/newt/mfg/meta.go b/newt/mfg/meta.go deleted file mode 100644 index 87aabe0..0000000 --- a/newt/mfg/meta.go +++ /dev/null @@ -1,247 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package mfg - -import ( - "bytes" - "crypto/sha256" - "encoding/binary" - - "mynewt.apache.org/newt/newt/flash" - "mynewt.apache.org/newt/util" -) - -// The "manufacturing meta region" is located at the end of the boot loader -// flash area. This region has the following structure. -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |Version (0x01) | 0xff padding | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | TLV type | TLV size | TLV data ("TLV size" bytes) ~ -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~ -// ~ ~ -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | TLV type | TLV size | TLV data ("TLV size" bytes) ~ -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~ -// ~ ~ -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Region size | 0xff padding | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Magic (0x3bb2a269) | -// +-+-+-+-+-+--+-+-+-+-end of boot loader area+-+-+-+-+-+-+-+-+-+-+ -// -// The number of TLVs is variable; two are shown above for illustrative -// purposes. -// -// Fields: -// <Header> -// 1. Version: Manufacturing meta version number; always 0x01. -// -// <TLVs> -// 2. TLV type: Indicates the type of data to follow. -// 3. TLV size: The number of bytes of data to follow. -// 4. TLV data: TLV-size bytes of data. -// -// <Footer> -// 5. Region size: The size, in bytes, of the entire manufacturing meta region; -// includes header, TLVs, and footer. -// 6. Magic: indicates the presence of the manufacturing meta region. - -const META_MAGIC = 0x3bb2a269 -const META_VERSION = 1 -const META_TLV_CODE_HASH = 0x01 -const META_TLV_CODE_FLASH_AREA = 0x02 - -const META_HASH_SZ = 32 -const META_FOOTER_SZ = 8 -const META_TLV_HASH_SZ = META_HASH_SZ -const META_TLV_FLASH_AREA_SZ = 12 - -type metaHeader struct { - version uint8 // 1 - pad8 uint8 // 0xff - pad16 uint16 // 0xffff -} - -type metaFooter struct { - size uint16 // Includes header, TLVs, and footer. - pad16 uint16 // 0xffff - magic uint32 // META_MAGIC -} - -type metaTlvHeader struct { - typ uint8 // Indicates the type of data to follow. - size uint8 // The number of bytes of data to follow. -} - -type metaTlvFlashArea struct { - header metaTlvHeader - areaId uint8 // Unique value identifying this flash area. - deviceId uint8 // Indicates host flash device (aka section number). - pad16 uint16 // 0xffff - offset uint32 // The byte offset within the flash device. - size uint32 // Size, in bytes, of entire flash area. -} - -type metaTlvHash struct { - header metaTlvHeader - hash [META_HASH_SZ]byte -} - -func writeElem(elem interface{}, buf *bytes.Buffer) error { - /* XXX: Assume target platform uses little endian. */ - if err := binary.Write(buf, binary.LittleEndian, elem); err != nil { - return util.ChildNewtError(err) - } - return nil -} - -func writeHeader(buf *bytes.Buffer) error { - hdr := metaHeader{ - version: META_VERSION, - pad8: 0xff, - pad16: 0xffff, - } - return writeElem(hdr, buf) -} - -func writeFooter(buf *bytes.Buffer) error { - ftr := metaFooter{ - size: uint16(buf.Len() + META_FOOTER_SZ), - pad16: 0xffff, - magic: META_MAGIC, - } - return writeElem(ftr, buf) -} - -func writeTlvHeader(typ uint8, size uint8, buf *bytes.Buffer) error { - tlvHdr := metaTlvHeader{ - typ: typ, - size: size, - } - return writeElem(tlvHdr, buf) -} - -// Writes a single entry of the flash map TLV. -func writeFlashMapEntry(area flash.FlashArea, buf *bytes.Buffer) error { - tlv := metaTlvFlashArea{ - header: metaTlvHeader{ - typ: META_TLV_CODE_FLASH_AREA, - size: META_TLV_FLASH_AREA_SZ, - }, - areaId: uint8(area.Id), - deviceId: uint8(area.Device), - pad16: 0xffff, - offset: uint32(area.Offset), - size: uint32(area.Size), - } - return writeElem(tlv, buf) -} - -// Writes a zeroed-out hash TLV. The hash's original value must be zero for -// the actual hash to be calculated later. After the actual value is -// calculated, it replaces the zeros in the TLV. -func writeZeroHash(buf *bytes.Buffer) error { - tlv := metaTlvHash{ - header: metaTlvHeader{ - typ: META_TLV_CODE_HASH, - size: META_TLV_HASH_SZ, - }, - hash: [META_HASH_SZ]byte{}, - } - return writeElem(tlv, buf) -} - -// @return meta-offset, hash-offset, error -func insertMeta(section0Data []byte, flashMap flash.FlashMap) ( - int, int, error) { - - buf := &bytes.Buffer{} - - if err := writeHeader(buf); err != nil { - return 0, 0, err - } - - for _, area := range flashMap.SortedAreas() { - if err := writeFlashMapEntry(area, buf); err != nil { - return 0, 0, err - } - } - - if err := writeZeroHash(buf); err != nil { - return 0, 0, err - } - hashSubOff := buf.Len() - META_HASH_SZ - - if err := writeFooter(buf); err != nil { - return 0, 0, err - } - - // The meta region gets placed at the very end of the boot loader slot. - bootArea, ok := flashMap.Areas[flash.FLASH_AREA_NAME_BOOTLOADER] - if !ok { - return 0, 0, - util.NewNewtError("Required boot loader flash area missing") - } - - if bootArea.Size < buf.Len() { - return 0, 0, util.FmtNewtError( - "Boot loader flash area too small to accommodate meta region; "+ - "boot=%d meta=%d", bootArea.Size, buf.Len()) - } - - metaOff := bootArea.Offset + bootArea.Size - buf.Len() - for i := metaOff; i < bootArea.Size; i++ { - if section0Data[i] != 0xff { - return 0, 0, util.FmtNewtError( - "Boot loader extends into meta region; "+ - "meta region starts at offset %d", metaOff) - } - } - - // Copy the meta region into the manufacturing image. The meta hash is - // still zeroed. - copy(section0Data[metaOff:], buf.Bytes()) - - return metaOff, metaOff + hashSubOff, nil -} - -// Calculates the SHA256 hash, using the full manufacturing image as input. -// Hash-calculation algorithm is as follows: -// 1. Concatenate sections in ascending order of index. -// 2. Zero out the 32 bytes that will contain the hash. -// 3. Apply SHA256 to the result. -// -// This function assumes that the 32 bytes of hash data have already been -// zeroed. -func calcMetaHash(sections [][]byte) []byte { - // Concatenate all sections. - blob := []byte{} - for _, section := range sections { - blob = append(blob, section...) - } - - // Calculate hash. - hash := sha256.Sum256(blob) - - return hash[:] -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/mfg/mfg.go ---------------------------------------------------------------------- diff --git a/newt/mfg/mfg.go b/newt/mfg/mfg.go deleted file mode 100644 index 98fbc37..0000000 --- a/newt/mfg/mfg.go +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package mfg - -import ( - "sort" - - "mynewt.apache.org/newt/newt/image" - "mynewt.apache.org/newt/newt/pkg" - "mynewt.apache.org/newt/newt/target" -) - -type MfgRawEntry struct { - device int - offset int - filename string - data []byte -} - -// A chunk of data in the manufacturing image. Can be a firmware image or a -// raw entry (contents of a data file). -type mfgPart struct { - device int - offset int - data []byte - name string -} - -type MfgImage struct { - basePkg *pkg.LocalPackage - - bsp *pkg.BspPackage - - boot *target.Target - images []*target.Target - rawEntries []MfgRawEntry - - version image.ImageVersion -} - -func (mi *MfgImage) SetVersion(ver image.ImageVersion) { - mi.version = ver -} - -func (mi *MfgImage) imgApps(imageIdx int) ( - app *pkg.LocalPackage, loader *pkg.LocalPackage) { - - if imageIdx >= len(mi.images) { - return - } - - t := mi.images[imageIdx] - app = t.App() - loader = t.Loader() - return -} - -func (mi *MfgImage) sectionIds() []int { - idMap := map[int]struct{}{} - - // The bootloader and images always go in section 0. - idMap[0] = struct{}{} - - for _, entry := range mi.rawEntries { - idMap[entry.device] = struct{}{} - } - - ids := make([]int, 0, len(idMap)) - for id, _ := range idMap { - ids = append(ids, id) - } - sort.Ints(ids) - - return ids -} - -func (mi *MfgImage) NumImages() int { - return len(mi.images) -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/mfg/paths.go ---------------------------------------------------------------------- diff --git a/newt/mfg/paths.go b/newt/mfg/paths.go deleted file mode 100644 index f05abb3..0000000 --- a/newt/mfg/paths.go +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package mfg - -import ( - "fmt" - "path/filepath" - "strconv" - - "mynewt.apache.org/newt/newt/builder" - "mynewt.apache.org/newt/newt/pkg" -) - -func MfgBinDir(mfgPkgName string) string { - return builder.BinRoot() + "/" + mfgPkgName -} - -func MfgBootDir(mfgPkgName string) string { - return MfgBinDir(mfgPkgName) + "/bootloader" -} - -func MfgBootBinPath(mfgPkgName string, appName string) string { - return MfgBootDir(mfgPkgName) + "/" + appName + ".elf.bin" -} - -func MfgBootElfPath(mfgPkgName string, appName string) string { - return MfgBootDir(mfgPkgName) + "/" + appName + ".elf" -} - -func MfgBootManifestPath(mfgPkgName string, appName string) string { - return MfgBootDir(mfgPkgName) + "/manifest.json" -} - -// Image indices start at 0. -func MfgImageBinDir(mfgPkgName string, imageIdx int) string { - return MfgBinDir(mfgPkgName) + "/image" + strconv.Itoa(imageIdx) -} - -func MfgImageImgPath(mfgPkgName string, imageIdx int, - appName string) string { - - return MfgImageBinDir(mfgPkgName, imageIdx) + "/" + appName + ".img" -} - -func MfgImageElfPath(mfgPkgName string, imageIdx int, - appName string) string { - - return MfgImageBinDir(mfgPkgName, imageIdx) + "/" + appName + ".elf" -} - -func MfgImageManifestPath(mfgPkgName string, imageIdx int) string { - return MfgImageBinDir(mfgPkgName, imageIdx) + "/manifest.json" -} - -func MfgSectionBinDir(mfgPkgName string) string { - return MfgBinDir(mfgPkgName) + "/sections" -} - -func MfgSectionBinPath(mfgPkgName string, sectionNum int) string { - return fmt.Sprintf("%s/%s-s%d.bin", MfgSectionBinDir(mfgPkgName), - filepath.Base(mfgPkgName), sectionNum) -} - -func MfgManifestPath(mfgPkgName string) string { - return MfgBinDir(mfgPkgName) + "/manifest.json" -} - -func (mi *MfgImage) ManifestPath() string { - return MfgManifestPath(mi.basePkg.Name()) -} - -func (mi *MfgImage) BootBinPath() string { - if mi.boot == nil { - return "" - } - - return MfgBootBinPath(mi.basePkg.Name(), - pkg.ShortName(mi.boot.App())) -} - -func (mi *MfgImage) BootElfPath() string { - if mi.boot == nil { - return "" - } - - return MfgBootElfPath(mi.basePkg.Name(), pkg.ShortName(mi.boot.App())) -} - -func (mi *MfgImage) BootManifestPath() string { - if mi.boot == nil { - return "" - } - - return MfgBootManifestPath(mi.basePkg.Name(), - pkg.ShortName(mi.boot.App())) -} - -func (mi *MfgImage) AppImgPath(imageIdx int) string { - app, _ := mi.imgApps(imageIdx) - if app == nil { - return "" - } - - return MfgImageImgPath(mi.basePkg.Name(), imageIdx, pkg.ShortName(app)) -} - -func (mi *MfgImage) AppElfPath(imageIdx int) string { - app, _ := mi.imgApps(imageIdx) - if app == nil { - return "" - } - - return MfgImageElfPath(mi.basePkg.Name(), imageIdx, pkg.ShortName(app)) -} - -func (mi *MfgImage) LoaderImgPath(imageIdx int) string { - _, loader := mi.imgApps(imageIdx) - if loader == nil { - return "" - } - - return MfgImageImgPath(mi.basePkg.Name(), imageIdx, pkg.ShortName(loader)) -} - -func (mi *MfgImage) LoaderElfPath(imageIdx int) string { - _, loader := mi.imgApps(imageIdx) - if loader == nil { - return "" - } - - return MfgImageElfPath(mi.basePkg.Name(), imageIdx, pkg.ShortName(loader)) -} - -func (mi *MfgImage) ImageManifestPath(imageIdx int) string { - if imageIdx >= len(mi.images) { - return "" - } - - return MfgImageManifestPath(mi.basePkg.Name(), imageIdx) -} - -func (mi *MfgImage) SectionBinPaths() []string { - sectionIds := mi.sectionIds() - - paths := make([]string, len(sectionIds)) - for i, sectionId := range sectionIds { - paths[i] = MfgSectionBinPath(mi.basePkg.Name(), sectionId) - } - return paths -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/mfg/read.go ---------------------------------------------------------------------- diff --git a/newt/mfg/read.go b/newt/mfg/read.go deleted file mode 100644 index 04520db..0000000 --- a/newt/mfg/read.go +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package mfg - -import ( - "strings" - - "mynewt.apache.org/newt/newt/builder" -) - -// @return mfg-image-path, error -func (mi *MfgImage) Upload() (string, error) { - // For now, we always upload section 0 only. - section0Path := MfgSectionBinPath(mi.basePkg.Name(), 0) - baseName := strings.TrimSuffix(section0Path, ".bin") - - envSettings := map[string]string{"MFG_IMAGE": "1"} - if err := builder.Load(baseName, mi.bsp, envSettings); err != nil { - return "", err - } - - return section0Path, nil -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/newt.go ---------------------------------------------------------------------- diff --git a/newt/newt.go b/newt/newt.go deleted file mode 100644 index 0dc8808..0000000 --- a/newt/newt.go +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package main - -import ( - "fmt" - "os" - "runtime" - - log "github.com/Sirupsen/logrus" - "github.com/spf13/cobra" - - "mynewt.apache.org/newt/newt/cli" - "mynewt.apache.org/newt/newt/newtutil" - "mynewt.apache.org/newt/util" -) - -var NewtLogLevel log.Level -var newtSilent bool -var newtQuiet bool -var newtVerbose bool -var newtLogFile string -var newtNumJobs int -var newtHelp bool - -func newtDfltNumJobs() int { - maxProcs := runtime.GOMAXPROCS(0) - numCpu := runtime.NumCPU() - - var numJobs int - if maxProcs < numCpu { - numJobs = maxProcs - } else { - numJobs = numCpu - } - - return numJobs -} - -func newtCmd() *cobra.Command { - newtHelpText := cli.FormatHelp(`Newt allows you to create your own embedded - application based on the Mynewt operating system. Newt provides both - build and package management in a single tool, which allows you to - compose an embedded application, and set of projects, and then build - the necessary artifacts from those projects. For more information - on the Mynewt operating system, please visit - https://mynewt.apache.org/.`) - newtHelpText += "\n\n" + cli.FormatHelp(`Please use the newt help command, - and specify the name of the command you want help for, for help on - how to use a specific command`) - newtHelpEx := " newt\n" - newtHelpEx += " newt help [<command-name>]\n" - newtHelpEx += " For help on <command-name>. If not specified, " + - "print this message." - - logLevelStr := "" - newtCmd := &cobra.Command{ - Use: "newt", - Short: "Newt is a tool to help you compose and build your own OS", - Long: newtHelpText, - Example: newtHelpEx, - PersistentPreRun: func(cmd *cobra.Command, args []string) { - verbosity := util.VERBOSITY_DEFAULT - if newtSilent { - verbosity = util.VERBOSITY_SILENT - } else if newtQuiet { - verbosity = util.VERBOSITY_QUIET - } else if newtVerbose { - verbosity = util.VERBOSITY_VERBOSE - } - - var err error - NewtLogLevel, err = log.ParseLevel(logLevelStr) - if err != nil { - cli.NewtUsage(nil, util.NewNewtError(err.Error())) - } - - err = util.Init(NewtLogLevel, newtLogFile, verbosity) - if err != nil { - cli.NewtUsage(nil, err) - } - - newtutil.NewtNumJobs = newtNumJobs - }, - Run: func(cmd *cobra.Command, args []string) { - cmd.Help() - }, - } - - newtCmd.PersistentFlags().BoolVarP(&newtVerbose, "verbose", "v", false, - "Enable verbose output when executing commands") - newtCmd.PersistentFlags().BoolVarP(&newtQuiet, "quiet", "q", false, - "Be quiet; only display error output") - newtCmd.PersistentFlags().BoolVarP(&newtSilent, "silent", "s", false, - "Be silent; don't output anything") - newtCmd.PersistentFlags().StringVarP(&logLevelStr, "loglevel", "l", - "WARN", "Log level") - newtCmd.PersistentFlags().StringVarP(&newtLogFile, "outfile", "o", - "", "Filename to tee output to") - newtCmd.PersistentFlags().IntVarP(&newtNumJobs, "jobs", "j", - newtDfltNumJobs(), "Number of concurrent build jobs") - newtCmd.PersistentFlags().BoolVarP(&newtHelp, "help", "h", - false, "Help for newt commands") - - versHelpText := cli.FormatHelp(`Display the Newt version number`) - versHelpEx := " newt version" - versCmd := &cobra.Command{ - Use: "version", - Short: "Display the Newt version number", - Long: versHelpText, - Example: versHelpEx, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("%s\n", newtutil.NewtVersionStr) - }, - } - - newtCmd.AddCommand(versCmd) - - return newtCmd -} - -func main() { - cmd := newtCmd() - - cli.AddBuildCommands(cmd) - cli.AddCompleteCommands(cmd) - cli.AddImageCommands(cmd) - cli.AddPackageCommands(cmd) - cli.AddProjectCommands(cmd) - cli.AddRunCommands(cmd) - cli.AddTargetCommands(cmd) - cli.AddValsCommands(cmd) - cli.AddMfgCommands(cmd) - - /* only pass the first two args to check for complete command */ - if len(os.Args) > 2 { - cmd.SilenceErrors = true - cmd.SilenceUsage = true - bc, _, err := cmd.Find(os.Args[1:2]) - tmpArgs := os.Args - os.Args = tmpArgs[0:2] - - if err == nil && bc.Name() == "complete" { - cli.GenerateTabCompleteValues() - bc.Execute() - return - } - os.Args = tmpArgs - cmd.SilenceErrors = false - cmd.SilenceUsage = false - } - - cmd.Execute() -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/newtutil/newtutil.go ---------------------------------------------------------------------- diff --git a/newt/newtutil/newtutil.go b/newt/newtutil/newtutil.go deleted file mode 100644 index ff79ffb..0000000 --- a/newt/newtutil/newtutil.go +++ /dev/null @@ -1,309 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package newtutil - -import ( - "fmt" - "os/user" - "sort" - "strconv" - "strings" - - log "github.com/Sirupsen/logrus" - "github.com/spf13/cast" - - "mynewt.apache.org/newt/newt/interfaces" - "mynewt.apache.org/newt/util" - "mynewt.apache.org/newt/viper" -) - -var NewtVersion Version = Version{1, 0, 0} -var NewtVersionStr string = "Apache Newt (incubating) version: 1.0.0-dev" -var NewtBlinkyTag string = "develop" -var NewtNumJobs int -var NewtForce bool - -const NEWTRC_DIR string = ".newt" -const REPOS_FILENAME string = "repos.yml" - -const CORE_REPO_NAME string = "apache-mynewt-core" -const ARDUINO_ZERO_REPO_NAME string = "mynewt_arduino_zero" - -type Version struct { - Major int64 - Minor int64 - Revision int64 -} - -func ParseVersion(s string) (Version, error) { - v := Version{} - parseErr := util.FmtNewtError("Invalid version string: %s", s) - - parts := strings.Split(s, ".") - if len(parts) != 3 { - return v, parseErr - } - - var err error - - v.Major, err = strconv.ParseInt(parts[0], 10, 64) - if err != nil { - return v, parseErr - } - - v.Minor, err = strconv.ParseInt(parts[1], 10, 64) - if err != nil { - return v, parseErr - } - - v.Revision, err = strconv.ParseInt(parts[2], 10, 64) - if err != nil { - return v, parseErr - } - - return v, nil -} - -func (v *Version) String() string { - return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Revision) -} - -func VerCmp(v1 Version, v2 Version) int64 { - if r := v1.Major - v2.Major; r != 0 { - return r - } - - if r := v1.Minor - v2.Minor; r != 0 { - return r - } - - if r := v1.Revision - v2.Revision; r != 0 { - return r - } - - return 0 -} - -// Contains general newt settings read from $HOME/.newt -var newtrc *viper.Viper - -func readNewtrc() *viper.Viper { - usr, err := user.Current() - if err != nil { - log.Warn("Failed to obtain user name") - return viper.New() - } - - dir := usr.HomeDir + "/" + NEWTRC_DIR - v, err := util.ReadConfig(dir, strings.TrimSuffix(REPOS_FILENAME, ".yml")) - if err != nil { - log.Debugf("Failed to read %s/%s file", dir, REPOS_FILENAME) - return viper.New() - } - - return v -} - -func Newtrc() *viper.Viper { - if newtrc != nil { - return newtrc - } - - newtrc = readNewtrc() - return newtrc -} - -func GetSliceFeatures(v *viper.Viper, features map[string]bool, - key string) []interface{} { - - val := v.Get(key) - vals := []interface{}{val} - - // Process the features in alphabetical order to ensure consistent - // results across repeated runs. - featureKeys := make([]string, 0, len(features)) - for feature, _ := range features { - featureKeys = append(featureKeys, feature) - } - sort.Strings(featureKeys) - - for _, feature := range featureKeys { - overwriteVal := v.Get(key + "." + feature + ".OVERWRITE") - if overwriteVal != nil { - return []interface{}{overwriteVal} - } - - appendVal := v.Get(key + "." + feature) - if appendVal != nil { - vals = append(vals, appendVal) - } - } - - return vals -} - -func GetStringMapFeatures(v *viper.Viper, features map[string]bool, - key string) map[string]interface{} { - - result := map[string]interface{}{} - - slice := GetSliceFeatures(v, features, key) - for _, itf := range slice { - sub := cast.ToStringMap(itf) - for k, v := range sub { - result[k] = v - } - } - - return result -} - -func GetStringFeatures(v *viper.Viper, features map[string]bool, - key string) string { - val := v.GetString(key) - - // Process the features in alphabetical order to ensure consistent - // results across repeated runs. - var featureKeys []string - for feature, _ := range features { - featureKeys = append(featureKeys, feature) - } - sort.Strings(featureKeys) - - for _, feature := range featureKeys { - overwriteVal := v.GetString(key + "." + feature + ".OVERWRITE") - if overwriteVal != "" { - val = strings.Trim(overwriteVal, "\n") - break - } - - appendVal := v.GetString(key + "." + feature) - if appendVal != "" { - val += " " + strings.Trim(appendVal, "\n") - } - } - return strings.TrimSpace(val) -} - -func GetBoolFeaturesDflt(v *viper.Viper, features map[string]bool, - key string, dflt bool) (bool, error) { - - s := GetStringFeatures(v, features, key) - if s == "" { - return dflt, nil - } - - b, err := strconv.ParseBool(s) - if err != nil { - return dflt, util.FmtNewtError("invalid bool value for %s: %s", - key, s) - } - - return b, nil -} - -func GetBoolFeatures(v *viper.Viper, features map[string]bool, - key string) (bool, error) { - - return GetBoolFeaturesDflt(v, features, key, false) -} - -func GetStringSliceFeatures(v *viper.Viper, features map[string]bool, - key string) []string { - - vals := GetSliceFeatures(v, features, key) - - strVals := []string{} - for _, v := range vals { - subVals := cast.ToStringSlice(v) - strVals = append(strVals, subVals...) - } - - return strVals -} - -// Parses a string of the following form: -// [@repo]<path/to/package> -// -// @return string repo name ("" if no repo) -// string package name -// error if invalid package string -func ParsePackageString(pkgStr string) (string, string, error) { - // remove possible trailing '/' - pkgStr = strings.TrimSuffix(pkgStr, "/") - - if strings.HasPrefix(pkgStr, "@") { - nameParts := strings.SplitN(pkgStr[1:], "/", 2) - if len(nameParts) == 1 { - return "", "", util.NewNewtError(fmt.Sprintf("Invalid package "+ - "string; contains repo but no package name: %s", pkgStr)) - } else { - return nameParts[0], nameParts[1], nil - } - } else { - return "", pkgStr, nil - } -} - -func FindRepoDesignator(s string) (int, int) { - start := strings.Index(s, "@") - if start == -1 { - return -1, -1 - } - - len := strings.Index(s[start:], "/") - if len == -1 { - return -1, -1 - } - - return start, len -} - -func ReplaceRepoDesignators(s string) (string, bool) { - start, len := FindRepoDesignator(s) - if start == -1 { - return s, false - } - repoName := s[start+1 : start+len] - - proj := interfaces.GetProject() - repoPath := proj.FindRepoPath(repoName) - if repoPath == "" { - return s, false - } - - // Trim common project base from repo path. - relRepoPath := strings.TrimPrefix(repoPath, proj.Path()+"/") - - return s[:start] + relRepoPath + s[start+len:], true -} - -func BuildPackageString(repoName string, pkgName string) string { - if repoName != "" { - return "@" + repoName + "/" + pkgName - } else { - return pkgName - } -} - -func GeneratedPreamble() string { - return fmt.Sprintf("/**\n * This file was generated by %s\n */\n\n", - NewtVersionStr) -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/pkg/bsp_package.go ---------------------------------------------------------------------- diff --git a/newt/pkg/bsp_package.go b/newt/pkg/bsp_package.go deleted file mode 100644 index 146347f..0000000 --- a/newt/pkg/bsp_package.go +++ /dev/null @@ -1,183 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package pkg - -import ( - "runtime" - "strings" - - "mynewt.apache.org/newt/newt/flash" - "mynewt.apache.org/newt/newt/interfaces" - "mynewt.apache.org/newt/newt/newtutil" - "mynewt.apache.org/newt/util" - "mynewt.apache.org/newt/viper" -) - -const BSP_YAML_FILENAME = "bsp.yml" - -type BspPackage struct { - *LocalPackage - CompilerName string - Arch string - LinkerScripts []string - Part2LinkerScripts []string /* scripts to link app to second partition */ - DownloadScript string - DebugScript string - FlashMap flash.FlashMap - BspV *viper.Viper -} - -func (bsp *BspPackage) resolvePathSetting( - features map[string]bool, key string) (string, error) { - - proj := interfaces.GetProject() - - val := newtutil.GetStringFeatures(bsp.BspV, features, key) - if val == "" { - return "", nil - } - path, err := proj.ResolvePath(bsp.Repo().Path(), val) - if err != nil { - return "", util.PreNewtError(err, - "BSP \"%s\" specifies invalid %s setting", - bsp.Name(), key) - } - return path, nil -} - -// Interprets a setting as either a single linker script or a list of linker -// scripts. -func (bsp *BspPackage) resolveLinkerScriptSetting( - features map[string]bool, key string) ([]string, error) { - - paths := []string{} - - // Assume config file specifies a list of scripts. - vals := newtutil.GetStringSliceFeatures(bsp.BspV, features, key) - if vals == nil { - // Couldn't read a list of scripts; try to interpret setting as a - // single script. - path, err := bsp.resolvePathSetting(features, key) - if err != nil { - return nil, err - } - - paths = append(paths, path) - } else { - proj := interfaces.GetProject() - - // Read each linker script from the list. - for _, val := range vals { - path, err := proj.ResolvePath(bsp.Repo().Path(), val) - if err != nil { - return nil, util.PreNewtError(err, - "BSP \"%s\" specifies invalid %s setting", - bsp.Name(), key) - } - - paths = append(paths, path) - } - } - - return paths, nil -} - -func (bsp *BspPackage) Reload(features map[string]bool) error { - var err error - - if features == nil { - features = map[string]bool{ - strings.ToUpper(runtime.GOOS): true, - } - } else { - features[strings.ToUpper(runtime.GOOS)] = true - } - bsp.BspV, err = util.ReadConfig(bsp.BasePath(), - strings.TrimSuffix(BSP_YAML_FILENAME, ".yml")) - if err != nil { - return err - } - bsp.AddCfgFilename(bsp.BasePath() + BSP_YAML_FILENAME) - - bsp.CompilerName = newtutil.GetStringFeatures(bsp.BspV, - features, "bsp.compiler") - - bsp.Arch = newtutil.GetStringFeatures(bsp.BspV, - features, "bsp.arch") - - bsp.LinkerScripts, err = bsp.resolveLinkerScriptSetting( - features, "bsp.linkerscript") - if err != nil { - return err - } - - bsp.Part2LinkerScripts, err = bsp.resolveLinkerScriptSetting( - features, "bsp.part2linkerscript") - if err != nil { - return err - } - - bsp.DownloadScript, err = bsp.resolvePathSetting( - features, "bsp.downloadscript") - if err != nil { - return err - } - bsp.DebugScript, err = bsp.resolvePathSetting( - features, "bsp.debugscript") - if err != nil { - return err - } - - if bsp.CompilerName == "" { - return util.NewNewtError("BSP does not specify a compiler " + - "(bsp.compiler)") - } - if bsp.Arch == "" { - return util.NewNewtError("BSP does not specify an architecture " + - "(bsp.arch)") - } - - ymlFlashMap := newtutil.GetStringMapFeatures(bsp.BspV, features, - "bsp.flash_map") - if ymlFlashMap == nil { - return util.NewNewtError("BSP does not specify a flash map " + - "(bsp.flash_map)") - } - bsp.FlashMap, err = flash.Read(ymlFlashMap) - if err != nil { - return err - } - - return nil -} - -func NewBspPackage(lpkg *LocalPackage) (*BspPackage, error) { - bsp := &BspPackage{ - CompilerName: "", - DownloadScript: "", - DebugScript: "", - BspV: viper.New(), - } - lpkg.Load() - bsp.LocalPackage = lpkg - err := bsp.Reload(nil) - - return bsp, err -} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/e31a7d31/newt/pkg/dependency.go ---------------------------------------------------------------------- diff --git a/newt/pkg/dependency.go b/newt/pkg/dependency.go deleted file mode 100644 index 4b15682..0000000 --- a/newt/pkg/dependency.go +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package pkg - -import ( - "mynewt.apache.org/newt/newt/interfaces" - "mynewt.apache.org/newt/newt/newtutil" - "mynewt.apache.org/newt/newt/repo" -) - -type Dependency struct { - Name string - Repo string -} - -func (dep *Dependency) String() string { - return newtutil.BuildPackageString(dep.Repo, dep.Name) -} - -func (dep *Dependency) SatisfiesDependency(pkg interfaces.PackageInterface) bool { - if dep.Name != pkg.Name() { - return false - } - - if dep.Repo != pkg.Repo().Name() { - return false - } - - return true -} - -func (dep *Dependency) setRepoAndName(parentRepo interfaces.RepoInterface, str string) error { - // First part is always repo/dependency name combination. - // If repo is present, string will always begin with a @ sign - // representing the repo name, followed by 'n' slashes. - repoName, pkgName, err := newtutil.ParsePackageString(str) - if err != nil { - return err - } - - if repoName != "" { - dep.Repo = repoName - dep.Name = pkgName - } else { - if parentRepo != nil { - dep.Repo = parentRepo.Name() - } else { - dep.Repo = repo.REPO_NAME_LOCAL - } - dep.Name = str - } - - return nil -} - -func (dep *Dependency) Init(parentRepo interfaces.RepoInterface, depStr string) error { - if err := dep.setRepoAndName(parentRepo, depStr); err != nil { - return err - } - - return nil -} - -func NewDependency(parentRepo interfaces.RepoInterface, depStr string) (*Dependency, error) { - dep := &Dependency{} - - if err := dep.Init(parentRepo, depStr); err != nil { - return nil, err - } - - return dep, nil -}
