blob: 0cde7f8956d5aab77c44940e24269175d5d81ba9 [file] [log] [blame]
/**
* 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
}