1a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov/* 2a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * Copyright (C) 2016 The Android Open Source Project 3a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * 4a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * Licensed under the Apache License, Version 2.0 (the "License"); 5a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * you may not use this file except in compliance with the License. 6a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * You may obtain a copy of the License at 7a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * 8a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * http://www.apache.org/licenses/LICENSE-2.0 9a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * 10a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * Unless required by applicable law or agreed to in writing, software 11a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * distributed under the License is distributed on an "AS IS" BASIS, 12a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * See the License for the specific language governing permissions and 14a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov * limitations under the License. 15a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov */ 16a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 17a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <assert.h> 18a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <fcntl.h> 19a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <gelf.h> 20a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <libelf.h> 21a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <sys/types.h> 22a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <stdbool.h> 23a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <unistd.h> 24a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <stdlib.h> 25a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <string.h> 26a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <stdint.h> 27a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <stdio.h> 28a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <stddef.h> 29a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <errno.h> 30a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 31a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <nanohub/nanohub.h> 32a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <nanohub/nanoapp.h> 33a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#include <nanohub/appRelocFormat.h> 34a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 35a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov//This code assumes it is run on a LE CPU with unaligned access abilities. Sorry. 36a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 37a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define FLASH_BASE 0x10000000 38a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define RAM_BASE 0x80000000 39a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 40a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define FLASH_SIZE 0x10000000 //256MB ought to be enough for everyone 41a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define RAM_SIZE 0x10000000 //256MB ought to be enough for everyone 42a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 43a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov//caution: double evaluation 44a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define IS_IN_RANGE_E(_val, _rstart, _rend) (((_val) >= (_rstart)) && ((_val) < (_rend))) 45a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define IS_IN_RANGE(_val, _rstart, _rsz) IS_IN_RANGE_E((_val), (_rstart), ((_rstart) + (_rsz))) 46a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define IS_IN_RAM(_val) IS_IN_RANGE(_val, RAM_BASE, RAM_SIZE) 47a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define IS_IN_FLASH(_val) IS_IN_RANGE(_val, FLASH_BASE, FLASH_SIZE) 48a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 49a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 50a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define NANO_RELOC_TYPE_RAM 0 51a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define NANO_RELOC_TYPE_FLASH 1 52a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define NANO_RELOC_LAST 2 //must be <= (RELOC_TYPE_MASK >> RELOC_TYPE_SHIFT) 53a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 54a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstruct RelocEntry { 55a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t where; 56a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t info; //bottom 8 bits is type, top 24 is sym idx 57a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov}; 58a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 59a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define RELOC_TYPE_ABS_S 2 60a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define RELOC_TYPE_ABS_D 21 61a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define RELOC_TYPE_SECT 23 62a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 63a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 64a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstruct SymtabEntry { 65a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t a; 66a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t addr; 67a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t b, c; 68a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov}; 69a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 70a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstruct NanoRelocEntry { 71a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t ofstInRam; 72a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t type; 73a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov}; 74a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 75a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#ifndef ARRAY_SIZE 76a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define ARRAY_SIZE(ary) (sizeof(ary) / sizeof((ary)[0])) 77a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#endif 78a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 79a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define DBG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__) 80a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define ERR(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) 81a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 82a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// Prints the given message followed by the most recent libelf error 83a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov#define ELF_ERR(fmt, ...) ERR(fmt ": %s\n", ##__VA_ARGS__, elf_errmsg(-1)) 84a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 85a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstruct ElfAppSection { 86a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov void *data; 87a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t size; 88a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov}; 89a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 90a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstruct ElfNanoApp { 91a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ElfAppSection flash; 92a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ElfAppSection data; 93a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ElfAppSection relocs; 94a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ElfAppSection symtab; 95a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 96a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // Not parsed from file, but constructed via genElfNanoRelocs 97a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ElfAppSection packedNanoRelocs; 98a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov}; 99a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 100a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic void fatalUsage(const char *name, const char *msg, const char *arg) 101a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 102a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (msg && arg) 103a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Error: %s: %s\n\n", msg, arg); 104a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (msg) 105a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Error: %s\n\n", msg); 106a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 107a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "USAGE: %s [-v] [-k <key id>] [-a <app id>] [-r] [-n <layout name>] [-i <layout id>] <input file> [<output file>]\n" 108a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " -v : be verbose\n" 109a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " -n <layout name> : app, os, key\n" 110a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " -i <layout id> : 1 (app), 2 (key), 3 (os)\n" 111a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " -f <layout flags>: 16-bit hex value, stored as layout-specific flags\n" 112a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " -a <app ID> : 64-bit hex number != 0\n" 113818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudov " -e <app version> : 32-bit hex number\n" 114a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " -k <key ID> : 64-bit hex number != 0\n" 115a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " -r : bare (no AOSP header); used only for inner OS image generation\n" 116a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " -s : treat input as statically linked ELF (app layout only)\n" 117a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " layout ID and layout name control the same parameter, so only one of them needs to be used\n" 118a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov , name); 119a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov exit(1); 120a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 121a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 122a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic uint8_t *packNanoRelocs(struct NanoRelocEntry *nanoRelocs, uint32_t outNumRelocs, uint32_t *finalPackedNanoRelocSz, bool verbose) 123a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 124a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t i, j, k; 125a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t *packedNanoRelocs; 126a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t packedNanoRelocSz; 127a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t lastOutType = 0, origin = 0; 128a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 129a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //sort by type and then offset 130a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov for (i = 0; i < outNumRelocs; i++) { 131a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct NanoRelocEntry t; 132a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 133a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov for (k = i, j = k + 1; j < outNumRelocs; j++) { 134a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (nanoRelocs[j].type > nanoRelocs[k].type) 135a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov continue; 136a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if ((nanoRelocs[j].type < nanoRelocs[k].type) || (nanoRelocs[j].ofstInRam < nanoRelocs[k].ofstInRam)) 137a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov k = j; 138a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 139a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memcpy(&t, nanoRelocs + i, sizeof(struct NanoRelocEntry)); 140a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memcpy(nanoRelocs + i, nanoRelocs + k, sizeof(struct NanoRelocEntry)); 141a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memcpy(nanoRelocs + k, &t, sizeof(struct NanoRelocEntry)); 142a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 143a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 144a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "SortedReloc[%3" PRIu32 "] = {0x%08" PRIX32 ",0x%02" PRIX8 "}\n", i, nanoRelocs[i].ofstInRam, nanoRelocs[i].type); 145a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 146a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 147a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //produce output nanorelocs in packed format 148a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs = malloc(outNumRelocs * 6); //definitely big enough 149a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocSz = 0; 150a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov for (i = 0; i < outNumRelocs; i++) { 151a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t displacement; 152a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 153a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (lastOutType != nanoRelocs[i].type) { //output type if ti changed 154a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (nanoRelocs[i].type - lastOutType == 1) { 155a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = TOKEN_RELOC_TYPE_NEXT; 156a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 157a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Out: RelocTC (1) // to 0x%02" PRIX8 "\n", nanoRelocs[i].type); 158a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 159a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else { 160a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = TOKEN_RELOC_TYPE_CHG; 161a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = nanoRelocs[i].type - lastOutType - 1; 162a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 163a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Out: RelocTC (0x%02" PRIX8 ") // to 0x%02" PRIX8 "\n", (uint8_t)(nanoRelocs[i].type - lastOutType - 1), nanoRelocs[i].type); 164a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 165a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov lastOutType = nanoRelocs[i].type; 166a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov origin = 0; 167a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 168a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov displacement = nanoRelocs[i].ofstInRam - origin; 169a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov origin = nanoRelocs[i].ofstInRam + 4; 170a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (displacement & 3) { 171a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Unaligned relocs are not possible!\n"); 172a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov exit(-5); 173a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 174a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov displacement /= 4; 175a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 176a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //might be start of a run. look into that 177a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!displacement) { 178a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov for (j = 1; j + i < outNumRelocs && j < MAX_RUN_LEN && nanoRelocs[j + i].type == lastOutType && nanoRelocs[j + i].ofstInRam - nanoRelocs[j + i - 1].ofstInRam == 4; j++); 179a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (j >= MIN_RUN_LEN) { 180a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 181a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Out: Reloc0 x%" PRIX32 "\n", j); 182a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = TOKEN_CONSECUTIVE; 183a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = j - MIN_RUN_LEN; 184a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov origin = nanoRelocs[j + i - 1].ofstInRam + 4; //reset origin to last one 185a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov i += j - 1; //loop will increment anyways, hence +1 186a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov continue; 187a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 188a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 189a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 190a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //produce output 191a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (displacement <= MAX_8_BIT_NUM) { 192a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 193a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Out: Reloc8 0x%02" PRIX32 "\n", displacement); 194a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement; 195a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 196a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (displacement <= MAX_16_BIT_NUM) { 197a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 198a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Out: Reloc16 0x%06" PRIX32 "\n", displacement); 199a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov displacement -= MAX_8_BIT_NUM; 200a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = TOKEN_16BIT_OFST; 201a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement; 202a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement >> 8; 203a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 204a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (displacement <= MAX_24_BIT_NUM) { 205a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 206a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Out: Reloc24 0x%08" PRIX32 "\n", displacement); 207a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov displacement -= MAX_16_BIT_NUM; 208a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = TOKEN_24BIT_OFST; 209a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement; 210a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement >> 8; 211a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement >> 16; 212a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 213a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else { 214a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 215a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Out: Reloc32 0x%08" PRIX32 "\n", displacement); 216a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = TOKEN_32BIT_OFST; 217a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement; 218a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement >> 8; 219a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement >> 16; 220a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs[packedNanoRelocSz++] = displacement >> 24; 221a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 222a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 223a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 224a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *finalPackedNanoRelocSz = packedNanoRelocSz; 225a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return packedNanoRelocs; 226a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 227a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 228a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic int finalizeAndWrite(uint8_t *buf, uint32_t bufUsed, uint32_t bufSz, FILE *out, uint32_t layoutFlags, uint64_t appId) 229a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 230a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov int ret; 231a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct AppInfo app; 232a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct SectInfo *sect; 233a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct BinHdr *bin = (struct BinHdr *) buf; 234a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ImageHeader outHeader = { 235a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .aosp = (struct nano_app_binary_t) { 236a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .header_version = 1, 237a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .magic = NANOAPP_AOSP_MAGIC, 238a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .app_id = appId, 239a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .app_version = bin->hdr.appVer, 240a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .flags = 0, // encrypted (1), signed (2) (will be set by other tools) 241a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 242a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .layout = (struct ImageLayout) { 243a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .magic = GOOGLE_LAYOUT_MAGIC, 244a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .version = 1, 245a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .payload = LAYOUT_APP, 246a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .flags = layoutFlags, 247a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 248a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }; 249a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t dataOffset = sizeof(outHeader) + sizeof(app); 250a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t hdrDiff = dataOffset - sizeof(*bin); 251a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov app.sect = bin->sect; 252a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov app.vec = bin->vec; 253a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 254a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov assertMem(bufUsed + hdrDiff, bufSz); 255a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 256a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memmove(buf + dataOffset, buf + sizeof(*bin), bufUsed - sizeof(*bin)); 257a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bufUsed += hdrDiff; 258a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memcpy(buf, &outHeader, sizeof(outHeader)); 259a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memcpy(buf + sizeof(outHeader), &app, sizeof(app)); 260a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect = &app.sect; 261a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 262a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //if we have any bytes to output, show stats 263a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (bufUsed) { 264a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t codeAndRoDataSz = sect->data_data; 265a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t relocsSz = sect->rel_end - sect->rel_start; 266a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t gotSz = sect->got_end - sect->data_start; 267a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t bssSz = sect->bss_end - sect->bss_start; 268a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 269a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr,"Final binary size %" PRIu32 " bytes\n", bufUsed); 270a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "\n"); 271a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, " FW header size (flash): %6zu bytes\n", FLASH_RELOC_OFFSET); 272a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, " Code + RO data (flash): %6" PRIu32 " bytes\n", codeAndRoDataSz); 273a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, " Relocs (flash): %6" PRIu32 " bytes\n", relocsSz); 274a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, " GOT + RW data (flash & RAM): %6" PRIu32 " bytes\n", gotSz); 275a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, " BSS (RAM): %6" PRIu32 " bytes\n", bssSz); 276a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "\n"); 277a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr,"Runtime flash use: %" PRIu32 " bytes\n", (uint32_t)(codeAndRoDataSz + relocsSz + gotSz + FLASH_RELOC_OFFSET)); 278a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr,"Runtime RAM use: %" PRIu32 " bytes\n", gotSz + bssSz); 279a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 280a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 281a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ret = fwrite(buf, bufUsed, 1, out) == 1 ? 0 : 2; 282a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (ret) 283a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Failed to write output file: %s\n", strerror(errno)); 284a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 285a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return ret; 286a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 287a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 288818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudovstatic int handleApp(uint8_t **pbuf, uint32_t bufUsed, FILE *out, uint32_t layoutFlags, uint64_t appId, uint32_t appVer, bool verbose) 289a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 290a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t i, numRelocs, numSyms, outNumRelocs = 0, packedNanoRelocSz; 291a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct NanoRelocEntry *nanoRelocs = NULL; 292a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct RelocEntry *relocs; 293a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct SymtabEntry *syms; 294a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t *packedNanoRelocs; 295a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t t; 296a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct BinHdr *bin; 297a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov int ret = -1; 298a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct SectInfo *sect; 299a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t *buf = *pbuf; 300a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t bufSz = bufUsed * 3 /2; 301a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 302a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //make buffer 50% bigger than bufUsed in case relocs grow out of hand 303a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov buf = reallocOrDie(buf, bufSz); 304a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *pbuf = buf; 305a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 306a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //sanity checks 307a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bin = (struct BinHdr*)buf; 308a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (bufUsed < sizeof(*bin)) { 309a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "File size too small\n"); 310a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 311a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 312a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 313a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (bin->hdr.magic != NANOAPP_FW_MAGIC) { 314a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Magic value is wrong: found %08" PRIX32 315a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov "; expected %08" PRIX32 "\n", 316a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bin->hdr.magic, NANOAPP_FW_MAGIC); 317a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 318a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 319a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 320a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect = &bin->sect; 321818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudov bin->hdr.appVer = appVer; 322a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 323a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //do some math 324a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov relocs = (struct RelocEntry*)(buf + sect->rel_start - FLASH_BASE); 325a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov syms = (struct SymtabEntry*)(buf + sect->rel_end - FLASH_BASE); 326a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov numRelocs = (sect->rel_end - sect->rel_start) / sizeof(struct RelocEntry); 327a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov numSyms = (bufUsed + FLASH_BASE - sect->rel_end) / sizeof(struct SymtabEntry); 328a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 329a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //sanity 330a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (numRelocs * sizeof(struct RelocEntry) + sect->rel_start != sect->rel_end) { 331a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Relocs of nonstandard size\n"); 332a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 333a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 334a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (numSyms * sizeof(struct SymtabEntry) + sect->rel_end != bufUsed + FLASH_BASE) { 335a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Syms of nonstandard size\n"); 336a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 337a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 338a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 339a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //show some info 340a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "\nRead %" PRIu32 " bytes of binary.\n", bufUsed); 341a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 342a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 343a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Found %" PRIu32 " relocs and a %" PRIu32 "-entry symbol table\n", numRelocs, numSyms); 344a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 345a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //handle relocs 346a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs = malloc(sizeof(struct NanoRelocEntry[numRelocs])); 347a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!nanoRelocs) { 348a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Failed to allocate a nano-reloc table\n"); 349a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 350a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 351a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 352a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov for (i = 0; i < numRelocs; i++) { 353a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t relocType = relocs[i].info & 0xff; 354a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t whichSym = relocs[i].info >> 8; 355a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t *valThereP; 356a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 357a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (whichSym >= numSyms) { 358a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Reloc %" PRIu32 " references a nonexistent symbol!\n" 359a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov "INFO:\n" 360a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " Where: 0x%08" PRIX32 "\n" 361a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " type: %" PRIu32 "\n" 362a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " sym: %" PRIu32 "\n", 363a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov i, relocs[i].where, relocs[i].info & 0xff, whichSym); 364a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 365a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 366a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 367a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) { 368a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const char *seg; 369a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 370a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Reloc[%3" PRIu32 "]:\n {@0x%08" PRIX32 ", type %3" PRIu32 ", -> sym[%3" PRIu32 "]: {@0x%08" PRIX32 "}, ", 371a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov i, relocs[i].where, relocs[i].info & 0xff, whichSym, syms[whichSym].addr); 372a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 373a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (IS_IN_RANGE_E(relocs[i].where, sect->bss_start, sect->bss_end)) 374a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov seg = ".bss"; 375a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (IS_IN_RANGE_E(relocs[i].where, sect->data_start, sect->data_end)) 376a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov seg = ".data"; 377a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (IS_IN_RANGE_E(relocs[i].where, sect->got_start, sect->got_end)) 378a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov seg = ".got"; 379a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (IS_IN_RANGE_E(relocs[i].where, FLASH_BASE, FLASH_BASE + sizeof(struct BinHdr))) 380a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov seg = "APPHDR"; 381a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else 382a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov seg = "???"; 383a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 384a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "in %s}\n", seg); 385a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 386a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov /* handle relocs inside the header */ 387a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (IS_IN_FLASH(relocs[i].where) && relocs[i].where - FLASH_BASE < sizeof(struct BinHdr) && relocType == RELOC_TYPE_SECT) { 388a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov /* relocs in header are special - runtime corrects for them */ 389a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (syms[whichSym].addr) { 390a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Weird in-header sect reloc %" PRIu32 " to symbol %" PRIu32 " with nonzero addr 0x%08" PRIX32 "\n", 391a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov i, whichSym, syms[whichSym].addr); 392a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 393a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 394a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 395a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov valThereP = (uint32_t*)(buf + relocs[i].where - FLASH_BASE); 396a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!IS_IN_FLASH(*valThereP)) { 397a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "In-header reloc %" PRIu32 " of location 0x%08" PRIX32 " is outside of FLASH!\n" 398a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov "INFO:\n" 399a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " type: %" PRIu32 "\n" 400a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " sym: %" PRIu32 "\n" 401a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " Sym Addr: 0x%08" PRIX32 "\n", 402a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov i, relocs[i].where, relocType, whichSym, syms[whichSym].addr); 403a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 404a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 405a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 406a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // binary header generated by objcopy, .napp header and final FW header in flash are of different size. 407a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // we subtract binary header offset here, so all the entry points are relative to beginning of "sect". 408a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // FW will use § as a base to call these vectors; no more problems with different header sizes; 409a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // Assumption: offsets between sect & vec, vec & code are the same in all images (or, in a simpler words, { sect, vec, code } 410a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // must go together). this is enforced by linker script, and maintained by all tools and FW download code in the OS. 411a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *valThereP -= FLASH_BASE + BINARY_RELOC_OFFSET; 412a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 413a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 414a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, " -> Nano reloc skipped for in-header reloc\n"); 415a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 416a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov continue; /* do not produce an output reloc */ 417a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 418a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 419a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!IS_IN_RAM(relocs[i].where)) { 420a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "In-header reloc %" PRIu32 " of location 0x%08" PRIX32 " is outside of RAM!\n" 421a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov "INFO:\n" 422a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " type: %" PRIu32 "\n" 423a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " sym: %" PRIu32 "\n" 424a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " Sym Addr: 0x%08" PRIX32 "\n", 425a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov i, relocs[i].where, relocType, whichSym, syms[whichSym].addr); 426a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 427a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 428a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 429a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov valThereP = (uint32_t*)(buf + relocs[i].where + sect->data_data - RAM_BASE - FLASH_BASE); 430a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 431a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs[outNumRelocs].ofstInRam = relocs[i].where - RAM_BASE; 432a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 433a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov switch (relocType) { 434a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov case RELOC_TYPE_ABS_S: 435a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov case RELOC_TYPE_ABS_D: 436a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov t = *valThereP; 437a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 438a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov (*valThereP) += syms[whichSym].addr; 439a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 440a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (IS_IN_FLASH(syms[whichSym].addr)) { 441a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov (*valThereP) -= FLASH_BASE + BINARY_RELOC_OFFSET; 442a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs[outNumRelocs].type = NANO_RELOC_TYPE_FLASH; 443a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 444a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (IS_IN_RAM(syms[whichSym].addr)) { 445a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov (*valThereP) -= RAM_BASE; 446a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs[outNumRelocs].type = NANO_RELOC_TYPE_RAM; 447a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 448a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else { 449a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Weird reloc %" PRIu32 " to symbol %" PRIu32 " in unknown memory space (addr 0x%08" PRIX32 ")\n", 450a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov i, whichSym, syms[whichSym].addr); 451a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 452a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 453a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 454a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, " -> Abs reference fixed up 0x%08" PRIX32 " -> 0x%08" PRIX32 "\n", t, *valThereP); 455a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov break; 456a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 457a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov case RELOC_TYPE_SECT: 458a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (syms[whichSym].addr) { 459a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Weird sect reloc %" PRIu32 " to symbol %" PRIu32 " with nonzero addr 0x%08" PRIX32 "\n", 460a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov i, whichSym, syms[whichSym].addr); 461a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 462a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 463a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 464a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov t = *valThereP; 465a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 466a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (IS_IN_FLASH(*valThereP)) { 467a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs[outNumRelocs].type = NANO_RELOC_TYPE_FLASH; 468a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *valThereP -= FLASH_BASE + BINARY_RELOC_OFFSET; 469a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 470a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (IS_IN_RAM(*valThereP)) { 471a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs[outNumRelocs].type = NANO_RELOC_TYPE_RAM; 472a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *valThereP -= RAM_BASE; 473a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 474a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else { 475a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Weird sec reloc %" PRIu32 " to symbol %" PRIu32 476a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " in unknown memory space (addr 0x%08" PRIX32 ")\n", 477a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov i, whichSym, *valThereP); 478a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 479a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 480a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 481a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, " -> Sect reference fixed up 0x%08" PRIX32 " -> 0x%08" PRIX32 "\n", t, *valThereP); 482a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov break; 483a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 484a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov default: 485a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Weird reloc %" PRIX32 " type %" PRIX32 " to symbol %" PRIX32 "\n", i, relocType, whichSym); 486a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 487a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 488a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 489a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (verbose) 490a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, " -> Nano reloc calculated as 0x%08" PRIX32 ",0x%02" PRIX8 "\n", nanoRelocs[i].ofstInRam, nanoRelocs[i].type); 491a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov outNumRelocs++; 492a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 493a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 494a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov packedNanoRelocs = packNanoRelocs(nanoRelocs, outNumRelocs, &packedNanoRelocSz, verbose); 495a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 496a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //overwrite original relocs and symtab with nanorelocs and adjust sizes 497a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memcpy(relocs, packedNanoRelocs, packedNanoRelocSz); 498a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bufUsed -= sizeof(struct RelocEntry[numRelocs]); 499a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bufUsed -= sizeof(struct SymtabEntry[numSyms]); 500a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bufUsed += packedNanoRelocSz; 501a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov assertMem(bufUsed, bufSz); 502a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->rel_end = sect->rel_start + packedNanoRelocSz; 503a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 504a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //sanity 505a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (sect->rel_end - FLASH_BASE != bufUsed) { 506a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Relocs end and file end not coincident\n"); 507a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 508a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 509a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 510a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //adjust headers for easy access (RAM) 511a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!IS_IN_RAM(sect->data_start) || !IS_IN_RAM(sect->data_end) || !IS_IN_RAM(sect->bss_start) || 512a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov !IS_IN_RAM(sect->bss_end) || !IS_IN_RAM(sect->got_start) || !IS_IN_RAM(sect->got_end)) { 513a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "data, bss, or got not in ram\n"); 514a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 515a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 516a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->data_start -= RAM_BASE; 517a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->data_end -= RAM_BASE; 518a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->bss_start -= RAM_BASE; 519a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->bss_end -= RAM_BASE; 520a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->got_start -= RAM_BASE; 521a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->got_end -= RAM_BASE; 522a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 523a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov //adjust headers for easy access (FLASH) 524a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!IS_IN_FLASH(sect->data_data) || !IS_IN_FLASH(sect->rel_start) || !IS_IN_FLASH(sect->rel_end)) { 525a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "data.data, or rel not in flash\n"); 526a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 527a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 528a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->data_data -= FLASH_BASE + BINARY_RELOC_OFFSET; 529a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->rel_start -= FLASH_BASE + BINARY_RELOC_OFFSET; 530a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sect->rel_end -= FLASH_BASE + BINARY_RELOC_OFFSET; 531a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 532a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ret = finalizeAndWrite(buf, bufUsed, bufSz, out, layoutFlags, appId); 533a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovout: 534a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov free(nanoRelocs); 535a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return ret; 536a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 537a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 538a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic void elfExtractSectionPointer(const Elf_Data *data, const char *name, struct ElfNanoApp *app) 539a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 540a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // Maps section names to their byte offset in struct ElfNanoApp. Note that 541a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // this assumes that the linker script puts text/code in the .flash section, 542a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // RW data in .data, that relocs for .data are included in .rel.data, and 543a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // the symbol table is emitted in .symtab 544a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const struct SectionMap { 545a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const char *name; 546a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t offset; 547a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } sectionMap[] = { 548a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov { 549a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .name = ".flash", 550a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .offset = offsetof(struct ElfNanoApp, flash), 551a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 552a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov { 553a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .name = ".data", 554a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .offset = offsetof(struct ElfNanoApp, data), 555a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 556a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov { 557a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .name = ".rel.data", 558a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .offset = offsetof(struct ElfNanoApp, relocs), 559a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 560a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov { 561a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .name = ".symtab", 562a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .offset = offsetof(struct ElfNanoApp, symtab), 563a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 564a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }; 565a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ElfAppSection *appSection; 566a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t *appBytes = (uint8_t *) app; 567a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 568a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov for (size_t i = 0; i < ARRAY_SIZE(sectionMap); i++) { 569a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (strcmp(name, sectionMap[i].name) != 0) { 570a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov continue; 571a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 572a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov appSection = (struct ElfAppSection *) &appBytes[sectionMap[i].offset]; 573a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 574a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov appSection->data = data->d_buf; 575a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov appSection->size = data->d_size; 576a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 577a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov DBG("Found section %s with size %zu", name, appSection->size); 578a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov break; 579a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 580a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 581a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 582a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// Populates a struct ElfNanoApp with data parsed from the ELF 583a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic bool elfParse(Elf *elf, struct ElfNanoApp *app) 584a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 585a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t shdrstrndx; 586a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov Elf_Scn *scn = NULL; 587a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov GElf_Shdr shdr; 588a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov char *sectionName; 589a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov Elf_Data *elf_data; 590a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 591a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memset(app, 0, sizeof(*app)); 592a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (elf_getshdrstrndx(elf, &shdrstrndx) != 0) { 593a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ELF_ERR("Couldn't get section name string table index"); 594a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 595a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 596a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 597a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov while ((scn = elf_nextscn(elf, scn)) != NULL) { 598a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (gelf_getshdr(scn, &shdr) != &shdr) { 599a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ELF_ERR("Error getting section header"); 600a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 601a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 602a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov sectionName = elf_strptr(elf, shdrstrndx, shdr.sh_name); 603a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 604a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov elf_data = elf_getdata(scn, NULL); 605a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!elf_data) { 606a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ELF_ERR("Error getting data for section %s", sectionName); 607a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 608a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 609a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 610a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov elfExtractSectionPointer(elf_data, sectionName, app); 611a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 612a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 613a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return true; 614a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 615a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 616a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic bool loadNanoappElfFile(const char *fileName, struct ElfNanoApp *app) 617a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 618a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov int fd; 619a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov Elf *elf; 620a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 621a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (elf_version(EV_CURRENT) == EV_NONE) { 622a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ELF_ERR("Failed to initialize ELF library"); 623a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 624a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 625a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 626a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fd = open(fileName, O_RDONLY, 0); 627a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (fd < 0) { 628a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ERR("Failed to open file %s for reading: %s", fileName, strerror(errno)); 629a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 630a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 631a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 632a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov elf = elf_begin(fd, ELF_C_READ, NULL); 633a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (elf == NULL) { 634a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ELF_ERR("Failed to open ELF"); 635a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 636a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 637a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 638a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!elfParse(elf, app)) { 639a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ERR("Failed to parse ELF file"); 640a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 641a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 642a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 643a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return true; 644a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 645a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 646a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// Subtracts the fixed memory region offset from an absolute address and returns 647a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// the associated NANO_RELOC_* value, or NANO_RELOC_LAST if the address is not 648a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// in the expected range. 649a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// Not strictly tied to ELF usage, but handled slightly differently. 650a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic uint8_t fixupAddrElf(uint32_t *addr) 651a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 652a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t type; 653a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 654a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // TODO: this assumes that the host running this tool has the same 655a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // endianness as the image file/target processor 656a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (IS_IN_FLASH(*addr)) { 657a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov DBG("Fixup addr 0x%08" PRIX32 " (flash) --> 0x%08" PRIX32, *addr, 658a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov (uint32_t) (*addr - (FLASH_BASE + BINARY_RELOC_OFFSET))); 659a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *addr -= FLASH_BASE + BINARY_RELOC_OFFSET; 660a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov type = NANO_RELOC_TYPE_FLASH; 661a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } else if (IS_IN_RAM(*addr)) { 662a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov DBG("Fixup addr 0x%08" PRIX32 " (ram) --> 0x%08" PRIX32, *addr, 663a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *addr - RAM_BASE); 664a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *addr -= RAM_BASE; 665a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov type = NANO_RELOC_TYPE_RAM; 666a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } else { 667a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov DBG("Error: invalid address 0x%08" PRIX32, *addr); 668a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov type = NANO_RELOC_LAST; 669a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 670a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 671a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return type; 672a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 673a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 674a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// Fixup addresses in the header to be relative. Not strictly tied to the ELF 675a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// format, but used only in that program flow in the current implementation. 676a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic bool fixupHeaderElf(const struct ElfNanoApp *app) 677a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 678a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct BinHdr *hdr = (struct BinHdr *) app->flash.data; 679a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 680a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov DBG("Appyling fixups to header"); 681a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (fixupAddrElf(&hdr->sect.data_start) != NANO_RELOC_TYPE_RAM || 682a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fixupAddrElf(&hdr->sect.data_end) != NANO_RELOC_TYPE_RAM || 683a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fixupAddrElf(&hdr->sect.bss_start) != NANO_RELOC_TYPE_RAM || 684a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fixupAddrElf(&hdr->sect.bss_end) != NANO_RELOC_TYPE_RAM || 685a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fixupAddrElf(&hdr->sect.got_start) != NANO_RELOC_TYPE_RAM || 686a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fixupAddrElf(&hdr->sect.got_end) != NANO_RELOC_TYPE_RAM) { 687a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ERR(".data, .bss, or .got not in RAM address space!"); 688a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 689a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 690a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 691a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (fixupAddrElf(&hdr->sect.rel_start) != NANO_RELOC_TYPE_FLASH || 692a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fixupAddrElf(&hdr->sect.rel_end) != NANO_RELOC_TYPE_FLASH || 693a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fixupAddrElf(&hdr->sect.data_data) != NANO_RELOC_TYPE_FLASH) { 694a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ERR(".data loadaddr, or .relocs not in flash address space!"); 695a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 696a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 697a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 698a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (fixupAddrElf(&hdr->vec.init) != NANO_RELOC_TYPE_FLASH || 699a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fixupAddrElf(&hdr->vec.end) != NANO_RELOC_TYPE_FLASH || 700a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fixupAddrElf(&hdr->vec.handle) != NANO_RELOC_TYPE_FLASH) { 701a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ERR("Entry point(s) not in flash address space!"); 702a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 703a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 704a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 705a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return true; 706a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 707a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 708a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// Fixup addresses in .data, .init_array/.fini_array, and .got, and generates 709a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// packed array of nano reloc entries. The app header must have already been 710a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov// fixed up. 711a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic bool genElfNanoRelocs(struct ElfNanoApp *app, bool verbose) 712a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 713a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const struct BinHdr *hdr = (const struct BinHdr *) app->flash.data; 714a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const struct SectInfo *sect = &hdr->sect; 715a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bool success = false; 716a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 717a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t numDataRelocs = app->relocs.size / sizeof(Elf32_Rel); 718a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t gotCount = (sect->got_end - sect->got_start) / sizeof(uint32_t); 719a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t numInitFuncs = (sect->bss_start - sect->data_end) / sizeof(uint32_t); 720a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 721a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t totalRelocCount = (numDataRelocs + numInitFuncs + gotCount); 722a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct NanoRelocEntry *nanoRelocs = malloc( 723a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov totalRelocCount * sizeof(struct NanoRelocEntry)); 724a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!nanoRelocs) { 725a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ERR("Couldn't allocate memory for nano relocs! Needed %zu bytes", 726a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov totalRelocCount * sizeof(struct NanoRelocEntry)); 727a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return false; 728a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 729a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 730a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t *data = app->data.data; 731a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const Elf32_Rel *relocs = (const Elf32_Rel *) app->relocs.data; 732a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const Elf32_Sym *syms = (const Elf32_Sym *) app->symtab.data; 733a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t numRelocs = 0; 734a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 735a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov DBG("Parsing relocs for .data (%zu):", numDataRelocs); 736a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov for (size_t i = 0; i < numDataRelocs; i++) { 737a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t type = ELF32_R_TYPE(relocs[i].r_info); 738a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t sym = ELF32_R_SYM(relocs[i].r_info); 739a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 740a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov DBG(" [%3zu] 0x%08" PRIx32 " type %2" PRIu32 " symIdx %3" PRIu32 741a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov " --> 0x%08" PRIx32, i, relocs[i].r_offset, type, sym, 742a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov syms[sym].st_value); 743a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // Note that R_ARM_TARGET1 is used for .init_array/.fini_array support, 744a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // and can be interpreted either as ABS32 or REL32, depending on the 745a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // runtime; we expect it to be ABS32. 746a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (type == R_ARM_ABS32 || type == R_ARM_TARGET1) { 747a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!IS_IN_RAM(relocs[i].r_offset)) { 748a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ERR("Reloc for .data not in RAM address range!"); 749a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 750a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 751a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t offset = relocs[i].r_offset - RAM_BASE; 752a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t *addr = (uint32_t *) &data[offset]; 753a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 754a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs[numRelocs].type = fixupAddrElf(addr); 755a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs[numRelocs].ofstInRam = offset; 756a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov numRelocs++; 757a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } else { 758a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // TODO: Assuming that the ELF only contains absolute addresses in 759a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // the .data section; may need to handle other relocation types in 760a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // the future 761a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ERR("Error: Unexpected reloc type %" PRIu32 " at index %zu", 762a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov type, i); 763a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov goto out; 764a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 765a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 766a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 767a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov DBG("Updating GOT entries (%zu):", gotCount); 768a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov for (uint32_t offset = sect->got_start; offset < sect->got_end; 769a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov offset += sizeof(uint32_t)) { 770a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t *addr = (uint32_t *) &data[offset]; 771a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // Skip values that are set to 0, these seem to be padding (?) 772a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (*addr) { 773a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs[numRelocs].type = fixupAddrElf(addr); 774a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs[numRelocs].ofstInRam = offset; 775a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov numRelocs++; 776a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 777a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 778a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 779a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t packedNanoRelocSz = 0; 780a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov app->packedNanoRelocs.data = packNanoRelocs( 781a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov nanoRelocs, numRelocs, &packedNanoRelocSz, verbose); 782a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov app->packedNanoRelocs.size = packedNanoRelocSz; 783a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov success = true; 784a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovout: 785a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov free(nanoRelocs); 786a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return success; 787a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 788a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 789818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudovstatic int handleAppStatic(const char *fileName, FILE *out, uint32_t layoutFlags, uint64_t appId, uint32_t appVer, bool verbose) 790a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 791a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ElfNanoApp app; 792a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 793a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!loadNanoappElfFile(fileName, &app) 794a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov || !fixupHeaderElf(&app) 795a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov || !genElfNanoRelocs(&app, verbose)) { 796a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov exit(2); 797a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 798a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 799a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // Construct a single contiguous buffer, with extra room to fit the 800a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // ImageHeader that will be prepended by finalizeAndWrite(). Note that this 801a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // will allocate a bit more space than is needed, because some of the data 802a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // from BinHdr will get discarded. 803a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // TODO: this should be refactored to just write the binary components in 804a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // order rather than allocating a big buffer, and moving data around 805a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t bufSize = app.flash.size + app.data.size + app.packedNanoRelocs.size 806a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov + sizeof(struct ImageHeader); 807a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t *buf = malloc(bufSize); 808a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!buf) { 809a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ERR("Failed to allocate %zu bytes for final app", bufSize); 810a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov exit(2); 811a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 812a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 813a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov size_t offset = 0; 814a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memcpy(buf, app.flash.data, app.flash.size); 815a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov offset += app.flash.size; 816a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memcpy(&buf[offset], app.data.data, app.data.size); 817a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov offset += app.data.size; 818a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov memcpy(&buf[offset], app.packedNanoRelocs.data, app.packedNanoRelocs.size); 819a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov offset += app.packedNanoRelocs.size; 820a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 821a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // Update rel_end in the header to reflect the packed reloc size 822a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct BinHdr *hdr = (struct BinHdr *) buf; 823a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov hdr->sect.rel_end = hdr->sect.rel_start + app.packedNanoRelocs.size; 824818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudov hdr->hdr.appVer = appVer; 825a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 826a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return finalizeAndWrite(buf, offset, bufSize, out, layoutFlags, appId); 827a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // TODO: should free all memory we allocated... just letting the OS handle 828a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov // it for now 829a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 830a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 831a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic int handleKey(uint8_t **pbuf, uint32_t bufUsed, FILE *out, uint32_t layoutFlags, uint64_t appId, uint64_t keyId) 832a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 833a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t *buf = *pbuf; 834a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct KeyInfo ki = { .data = keyId }; 835a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bool good = true; 836a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 837a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ImageHeader outHeader = { 838a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .aosp = (struct nano_app_binary_t) { 839a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .header_version = 1, 840a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .magic = NANOAPP_AOSP_MAGIC, 841a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .app_id = appId, 842a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 843a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .layout = (struct ImageLayout) { 844a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .magic = GOOGLE_LAYOUT_MAGIC, 845a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .version = 1, 846a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .payload = LAYOUT_KEY, 847a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .flags = layoutFlags, 848a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 849a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }; 850a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 851a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov good = good && fwrite(&outHeader, sizeof(outHeader), 1, out) == 1; 852a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov good = good && fwrite(&ki, sizeof(ki), 1, out) == 1; 853a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov good = good && fwrite(buf, bufUsed, 1, out) == 1; 854a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 855a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return good ? 0 : 2; 856a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 857a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 858a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovstatic int handleOs(uint8_t **pbuf, uint32_t bufUsed, FILE *out, uint32_t layoutFlags, bool bare) 859a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 860a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t *buf = *pbuf; 861a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bool good; 862a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 863a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct OsUpdateHdr os = { 864a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .magic = OS_UPDT_MAGIC, 865a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .marker = OS_UPDT_MARKER_INPROGRESS, 866a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .size = bufUsed 867a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }; 868a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 869a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov struct ImageHeader outHeader = { 870a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .aosp = (struct nano_app_binary_t) { 871a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .header_version = 1, 872a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .magic = NANOAPP_AOSP_MAGIC, 873a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 874a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .layout = (struct ImageLayout) { 875a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .magic = GOOGLE_LAYOUT_MAGIC, 876a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .version = 1, 877a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .payload = LAYOUT_OS, 878a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov .flags = layoutFlags, 879a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }, 880a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov }; 881a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 882a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!bare) 883a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov good = fwrite(&outHeader, sizeof(outHeader), 1, out) == 1; 884a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else 885a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov good = fwrite(&os, sizeof(os), 1, out) == 1; 886a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov good = good && fwrite(buf, bufUsed, 1, out) == 1; 887a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 888a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return good ? 0 : 2; 889a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 890a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 891a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudovint main(int argc, char **argv) 892a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov{ 893a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t bufUsed = 0; 894a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bool verbose = false; 895a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint8_t *buf = NULL; 896a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint64_t appId = 0; 897a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint64_t keyId = 0; 898818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudov uint32_t appVer = 0; 899a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t layoutId = 0; 900a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t layoutFlags = 0; 901a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov int ret = -1; 902a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t *u32Arg = NULL; 903a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint64_t *u64Arg = NULL; 904a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const char **strArg = NULL; 905a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const char *appName = argv[0]; 906a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov int posArgCnt = 0; 907a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const char *posArg[2] = { NULL }; 908a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov FILE *out = NULL; 909a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const char *layoutName = "app"; 910a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov const char *prev = NULL; 911a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bool bareData = false; 912a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bool staticElf = false; 913a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 914a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov for (int i = 1; i < argc; i++) { 915a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov char *end = NULL; 916a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (argv[i][0] == '-') { 917a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov prev = argv[i]; 918a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!strcmp(argv[i], "-v")) 919a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov verbose = true; 920a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (!strcmp(argv[i], "-r")) 921a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov bareData = true; 922a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (!strcmp(argv[i], "-s")) 923a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov staticElf = true; 924a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (!strcmp(argv[i], "-a")) 925a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov u64Arg = &appId; 926818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudov else if (!strcmp(argv[i], "-e")) 927818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudov u32Arg = &appVer; 928a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (!strcmp(argv[i], "-k")) 929a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov u64Arg = &keyId; 930a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (!strcmp(argv[i], "-n")) 931a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov strArg = &layoutName; 932a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (!strcmp(argv[i], "-i")) 933a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov u32Arg = &layoutId; 934a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (!strcmp(argv[i], "-f")) 935a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov u32Arg = &layoutFlags; 936a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else 937a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "unknown argument", argv[i]); 938a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } else { 939a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (u64Arg) { 940a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint64_t tmp = strtoull(argv[i], &end, 16); 941a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (*end == '\0') 942a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *u64Arg = tmp; 943a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov u64Arg = NULL; 944a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } else if (u32Arg) { 945a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov uint32_t tmp = strtoul(argv[i], &end, 16); 946a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (*end == '\0') 947a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *u32Arg = tmp; 948a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov u32Arg = NULL; 949a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } else if (strArg) { 950a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov *strArg = argv[i]; 951a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov strArg = NULL; 952a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } else { 953a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (posArgCnt < 2) 954a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov posArg[posArgCnt++] = argv[i]; 955a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else 956a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "too many positional arguments", argv[i]); 957a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 958a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov prev = NULL; 959a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 960a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 961a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (prev) 962a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "missing argument after", prev); 963a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 964a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!posArgCnt) 965a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "missing input file name", NULL); 966a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 967a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!layoutId) { 968a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (strcmp(layoutName, "app") == 0) 969a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov layoutId = LAYOUT_APP; 970a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (strcmp(layoutName, "os") == 0) 971a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov layoutId = LAYOUT_OS; 972a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else if (strcmp(layoutName, "key") == 0) 973a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov layoutId = LAYOUT_KEY; 974a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else 975a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "Invalid layout name", layoutName); 976a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 977a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 978a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (staticElf && layoutId != LAYOUT_APP) 979a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "Only app layout is supported for static option", NULL); 980a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 981a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (layoutId == LAYOUT_APP && !appId) 982a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "App layout requires app ID", NULL); 983a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (layoutId == LAYOUT_KEY && !keyId) 984a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "Key layout requires key ID", NULL); 985a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (layoutId == LAYOUT_OS && (keyId || appId)) 986a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "OS layout does not need any ID", NULL); 987a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 988a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!staticElf) { 989a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov buf = loadFile(posArg[0], &bufUsed); 990a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fprintf(stderr, "Read %" PRIu32 " bytes\n", bufUsed); 991a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 992a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 993a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!posArg[1]) 994a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov out = stdout; 995a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov else 996a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov out = fopen(posArg[1], "w"); 997a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (!out) 998a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fatalUsage(appName, "failed to create/open output file", posArg[1]); 999a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 1000a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov switch(layoutId) { 1001a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov case LAYOUT_APP: 1002a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov if (staticElf) { 1003818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudov ret = handleAppStatic(posArg[0], out, layoutFlags, appId, appVer, verbose); 1004a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } else { 1005818edb87a006750d90ce63e798cd7ab48798e538Alexey Polyudov ret = handleApp(&buf, bufUsed, out, layoutFlags, appId, appVer, verbose); 1006a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 1007a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov break; 1008a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov case LAYOUT_KEY: 1009a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ret = handleKey(&buf, bufUsed, out, layoutFlags, appId, keyId); 1010a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov break; 1011a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov case LAYOUT_OS: 1012a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov ret = handleOs(&buf, bufUsed, out, layoutFlags, bareData); 1013a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov break; 1014a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov } 1015a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov 1016a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov free(buf); 1017a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov fclose(out); 1018a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov return ret; 1019a2a09914775591691046341c06d1286a303ec0a9Alexey Polyudov} 1020