Home | History | Annotate | Download | only in nanohub
      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