| /** |
| * 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 manifest |
| |
| import ( |
| "encoding/hex" |
| "encoding/json" |
| "io/ioutil" |
| |
| "github.com/apache/mynewt-artifact/errors" |
| "github.com/apache/mynewt-artifact/flash" |
| "github.com/apache/mynewt-artifact/sec" |
| ) |
| |
| type MfgManifestTarget struct { |
| Name string `json:"name"` |
| Offset int `json:"offset"` |
| BinPath string `json:"bin_path,omitempty"` |
| ImagePath string `json:"image_path,omitempty"` |
| HexPath string `json:"hex_path,omitempty"` |
| ManifestPath string `json:"manifest_path"` |
| Extra map[string]interface{} `json:"extra,omitempty"` |
| } |
| |
| type MfgManifestRaw struct { |
| Filename string `json:"filename"` |
| Offset int `json:"offset"` |
| Size int `json:"size"` |
| BinPath string `json:"bin_path"` |
| Extra map[string]interface{} `json:"extra,omitempty"` |
| } |
| |
| type MfgManifestMetaMmr struct { |
| Area string `json:"area"` |
| Device int `json:"_device"` |
| EndOffset int `json:"_end_offset"` |
| } |
| |
| type MfgManifestMeta struct { |
| EndOffset int `json:"end_offset"` |
| Size int `json:"size"` |
| Hash bool `json:"hash_present"` |
| FlashMap bool `json:"flash_map_present"` |
| Mmrs []MfgManifestMetaMmr `json:"mmrs,omitempty"` |
| } |
| |
| type MfgManifestSig struct { |
| Type string `json:"type"` |
| Key string `json:"key"` |
| Sig string `json:"sig"` |
| } |
| |
| type MfgManifest struct { |
| Name string `json:"name"` |
| BuildTime string `json:"build_time"` |
| Format int `json:"format"` |
| MfgHash string `json:"mfg_hash"` |
| Version string `json:"version"` |
| Device int `json:"device"` |
| BinPath string `json:"bin_path"` |
| HexPath string `json:"hex_path"` |
| Bsp string `json:"bsp"` |
| EraseVal byte `json:"erase_val"` |
| Signatures []MfgManifestSig `json:"signatures,omitempty"` |
| FlashAreas []flash.FlashArea `json:"flash_map"` |
| |
| Targets []MfgManifestTarget `json:"targets"` |
| Raws []MfgManifestRaw `json:"raws"` |
| Meta *MfgManifestMeta `json:"meta,omitempty"` |
| } |
| |
| // ReadMfgManifest reads a JSON mfg manifest from a byte slice and produces an |
| // MfgManifest object. |
| func ParseMfgManifest(jsonText []byte) (MfgManifest, error) { |
| m := MfgManifest{ |
| // Backwards compatibility: assume 0xff if unspecified. |
| EraseVal: 0xff, |
| } |
| |
| if err := json.Unmarshal(jsonText, &m); err != nil { |
| return m, errors.Wrapf(err, "failure decoding mfg manifest") |
| } |
| |
| return m, nil |
| } |
| |
| // ReadMfgManifest reads a JSON mfg manifest from a file and produces an |
| // MfgManifest object. |
| func ReadMfgManifest(path string) (MfgManifest, error) { |
| content, err := ioutil.ReadFile(path) |
| if err != nil { |
| return MfgManifest{}, errors.Wrapf(err, |
| "failed to read mfg manifest file") |
| } |
| |
| m, err := ParseMfgManifest(content) |
| if err != nil { |
| return m, errors.Wrapf(err, "path=%s", path) |
| } |
| |
| return m, nil |
| } |
| |
| // IsBoot indicates whether an mfg manifest target is a boot loader. |
| func (mt *MfgManifestTarget) IsBoot() bool { |
| return mt.BinPath != "" |
| } |
| |
| // MarshalJson produces a JSON representation of an mfg manifest. |
| func (m *MfgManifest) MarshalJson() ([]byte, error) { |
| buffer, err := json.MarshalIndent(m, "", " ") |
| if err != nil { |
| return nil, errors.Wrapf(err, "cannot encode mfg manifest") |
| } |
| |
| return buffer, nil |
| } |
| |
| // FindFlashAreaDevOff searches an mfg manifest for a flash area with the |
| // specified device and offset. |
| func (m *MfgManifest) FindFlashAreaDevOff(device int, offset int) *flash.FlashArea { |
| for i, _ := range m.FlashAreas { |
| fa := &m.FlashAreas[i] |
| if fa.Device == device && fa.Offset == offset { |
| return fa |
| } |
| } |
| |
| return nil |
| } |
| |
| // FindFlashAreaName searches an mfg manifest for a flash area with the |
| // specified name. |
| func (m *MfgManifest) FindFlashAreaName(name string) *flash.FlashArea { |
| for i, _ := range m.FlashAreas { |
| fa := &m.FlashAreas[i] |
| if fa.Name == name { |
| return fa |
| } |
| } |
| |
| return nil |
| } |
| |
| // SecSig converts the provided mfg manifest signature into a sec.Sig object. |
| func (ms *MfgManifestSig) SecSig() (sec.Sig, error) { |
| keyHash, err := hex.DecodeString(ms.Key) |
| if err != nil { |
| return sec.Sig{}, errors.Errorf( |
| "invalid hex-encoded key hash: %s", ms.Key) |
| } |
| |
| data, err := hex.DecodeString(ms.Sig) |
| if err != nil { |
| return sec.Sig{}, errors.Errorf( |
| "invalid hex-encoded signature: %s", ms.Sig) |
| } |
| |
| return sec.Sig{ |
| KeyHash: keyHash, |
| Data: data, |
| }, nil |
| } |
| |
| // SecSigs converts all the signutures in the provided mfg manifest into |
| // sec.Sig objects. |
| func (m *MfgManifest) SecSigs() ([]sec.Sig, error) { |
| var sigs []sec.Sig |
| for _, ms := range m.Signatures { |
| s, err := ms.SecSig() |
| if err != nil { |
| return nil, err |
| } |
| |
| sigs = append(sigs, s) |
| } |
| |
| return sigs, nil |
| } |