1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _APP_RELOC_FORMAT_H_ 18 #define _APP_RELOC_FORMAT_H_ 19 20 21 /* 22 * INTRODUCTION 23 * 24 * This is the relocation format we use for Cortex-M4F cpu. This format is 25 * consistent with what GCC will produce with our app-compilation flags. So 26 * what will it produce? Relocs will ONLY be in RAM, always be word-sized, 27 * always be word-aligned, and never overlap. We use all of that. How do we 28 * encode? The relocs format is a bytestream. The decoder is conceptually two 29 * passes, though it can easily be implemented as a single pass. The first pass 30 * unpacks the bytestream into a list of TOKENS and NUMBERS. The second then 31 * uses those to reconstruct the list of relocs. 32 * 33 * 34 * PASS #1 - unpacking 35 * 36 * Each iteration, it will read a byte from the input byte stream, until none 37 * are available. This first byte will tell it what to do next. All values that 38 * are <= MAX_8_BIT_NUM, are put directly as a NUMBER into the output list. 39 * The remaining possibly values all require special handling, which will be 40 * described now: 41 * TOKEN_32BIT_OFST: 4 bytes follow. They are to be treated as a single 42 * 32-bit little-endian value. This value is put into 43 * the output list directly as a NUMBER. 44 * TOKEN_24BIT_OFST: 3 bytes follow. They are to be treated as a single 45 * 24-bit little-endian value. MAX_16_BIT_NUM is added 46 * to it, then this value is put into the output list 47 * as a NUMBER. 48 * TOKEN_16BIT_OFST: 2 bytes follow. They are to be treated as a single 49 * 16-bit little-endian value. MAX_8_BIT_NUM is added 50 * to it, then this value is put into the output list 51 * as a NUMBER. 52 * TOKEN_CONSECUTIVE: 1 byte follows. It is read, MIN_RUN_LEN is added to 53 * it. That many zero-valued NUMBERS are added to the 54 * output list. 55 * TOKEN_RELOC_TYPE_CHG: 1 byte follows. It is read, one is added to it, and 56 * a TYPE_CHANGE token with that value is added to the 57 * output list. 58 * TOKEN_RELOC_TYPE_NEXT: a TYPE_CHANGE token with a value of 1 is added to 59 * the output list. 60 * 61 * 62 * PASS #2 - decoding 63 * 64 * The decoder is stateful. Initially the decoder state is representable as: 65 * {reloc_type: 0, ofst: 0}. The decoder will work by removig one item at a 66 * time from the head of the list generated by PASS #1, and acting on it, until 67 * no more exist. It will produce {reloc_type, reloc_offset} tuples, which can 68 * then be used to perform actual relocations. Unpon reading a TYPE_CHANGE 69 * token, "reloc_type" in the decoder's state shall be incremented by the value 70 * the token carries, and "ofst" shall be set to zero. Upon reading a NUMBER, 71 * the decoder shall: 72 * a. calculate t = "ofst" + (that NUMBER's value) * 4 73 * b. store t + 4 into "ofst" 74 * c. produce an output tuple {"reloc_type", t} 75 * 76 * 77 * At the end of these two passes a list of tuples exists that has all reloc types 78 * and offsets. this list can be easily walked and relocations performed. 79 */ 80 81 82 83 //offset is always from previous reloc's NEXT word! 84 #define TOKEN_RELOC_TYPE_NEXT 0xFF // reloc type changed to previous + 1 85 #define TOKEN_RELOC_TYPE_CHG 0xFE // reloc type changed (followed by a byte represeting "reloc_type" increment minus 1) 86 #define TOKEN_CONSECUTIVE 0xFD // followed by 8-bit number of directly following words to relocate (in addition to the one we relocated using previous reloc) minus 3 (2 is break-even point) 87 #define TOKEN_16BIT_OFST 0xFC // followed by 16-bit x, such that the value we want to represent is x + MAX_8_BIT_NUM 88 #define TOKEN_24BIT_OFST 0xFB // followed by 24-bit x, such that the value we want to represent is x + MAX_16_BIT_NUM 89 #define TOKEN_32BIT_OFST 0xFA // followed by 32-bit value we want to represent, sent directly 90 #define MAX_8_BIT_NUM 0xF9 91 #define MAX_16_BIT_NUM (0xFFFF + MAX_8_BIT_NUM) 92 #define MAX_24_BIT_NUM (0xFFFFFF + MAX_16_BIT_NUM) 93 #define MIN_RUN_LEN 3 //run count does not include first element 94 #define MAX_RUN_LEN (0xff + MIN_RUN_LEN) 95 96 97 98 99 #endif 100