flash/flash.go (116 lines of code) (raw):

/** * 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 }