blob: 5903fb2807456b61315d9caf9de10fa5c7e934fb [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 flash
import (
"fmt"
"sort"
)
const FLASH_AREA_NAME_BOOTLOADER = "FLASH_AREA_BOOTLOADER"
const FLASH_AREA_NAME_IMAGE_0 = "FLASH_AREA_IMAGE_0"
const FLASH_AREA_NAME_IMAGE_1 = "FLASH_AREA_IMAGE_1"
const FLASH_AREA_NAME_IMAGE_SCRATCH = "FLASH_AREA_IMAGE_SCRATCH"
const AREA_USER_ID_MIN = 16
var SYSTEM_AREA_NAME_ID_MAP = map[string]int{
FLASH_AREA_NAME_BOOTLOADER: 0,
FLASH_AREA_NAME_IMAGE_0: 1,
FLASH_AREA_NAME_IMAGE_1: 2,
FLASH_AREA_NAME_IMAGE_SCRATCH: 3,
}
type FlashArea struct {
Name string `json:"name"`
Id int `json:"id"`
Device int `json:"device"`
Offset int `json:"offset"`
Size int `json:"size"`
}
type areaOffSorter struct {
areas []FlashArea
}
func (s areaOffSorter) Len() int {
return len(s.areas)
}
func (s areaOffSorter) Swap(i, j int) {
s.areas[i], s.areas[j] = s.areas[j], s.areas[i]
}
func (s areaOffSorter) Less(i, j int) bool {
ai := s.areas[i]
aj := s.areas[j]
if ai.Device < aj.Device {
return true
}
if ai.Device > aj.Device {
return false
}
return ai.Offset < aj.Offset
}
func SortFlashAreasByDevOff(areas []FlashArea) []FlashArea {
sorter := areaOffSorter{
areas: make([]FlashArea, len(areas)),
}
for i, a := range areas {
sorter.areas[i] = a
}
sort.Sort(sorter)
return sorter.areas
}
func SortFlashAreasById(areas []FlashArea) []FlashArea {
idMap := make(map[int]FlashArea, len(areas))
ids := make([]int, 0, len(areas))
for _, area := range areas {
idMap[area.Id] = area
ids = append(ids, area.Id)
}
sort.Ints(ids)
sorted := make([]FlashArea, len(ids))
for i, id := range ids {
sorted[i] = idMap[id]
}
return sorted
}
func areasDistinct(a FlashArea, b FlashArea) bool {
if a.Device != b.Device {
return true
}
var lo FlashArea
var hi FlashArea
if a.Offset < b.Offset {
lo = a
hi = b
} else {
lo = b
hi = a
}
return lo.Offset+lo.Size <= hi.Offset
}
// @return overlapping-areas, id-conflicts.
func DetectErrors(areas []FlashArea) ([][]FlashArea, [][]FlashArea) {
var overlaps [][]FlashArea
var conflicts [][]FlashArea
for i := 0; i < len(areas)-1; i++ {
iarea := areas[i]
for j := i + 1; j < len(areas); j++ {
jarea := areas[j]
if !areasDistinct(iarea, jarea) {
overlaps = append(overlaps, []FlashArea{iarea, jarea})
}
if iarea.Id == jarea.Id {
conflicts = append(conflicts, []FlashArea{iarea, jarea})
}
}
}
return overlaps, conflicts
}
func ErrorText(overlaps [][]FlashArea, conflicts [][]FlashArea) string {
str := ""
if len(conflicts) > 0 {
str += "Conflicting flash area IDs detected:\n"
for _, pair := range conflicts {
str += fmt.Sprintf(" (%d) %s =/= %s\n",
pair[0].Id-AREA_USER_ID_MIN, pair[0].Name, pair[1].Name)
}
}
if len(overlaps) > 0 {
str += "Overlapping flash areas detected:\n"
for _, pair := range overlaps {
str += fmt.Sprintf(" %s =/= %s\n", pair[0].Name, pair[1].Name)
}
}
return str
}