Home | History | Annotate | Download | only in programmer
      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 package org.chromium.latency.walt.programmer;
     18 
     19 import android.util.Log;
     20 
     21 import java.io.BufferedReader;
     22 import java.io.IOException;
     23 import java.io.InputStream;
     24 import java.io.InputStreamReader;
     25 import java.text.ParseException;
     26 import java.util.Arrays;
     27 
     28 class FirmwareImage {
     29     private static final String TAG = "FirmwareImage";
     30 
     31     private boolean atEOF = false;
     32     private byte[] image = new byte[DeviceConstants.FIRMWARE_SIZE];
     33     private boolean[] mask = new boolean[DeviceConstants.FIRMWARE_SIZE];
     34 
     35     boolean shouldWrite(int addr, int len) {
     36         if (addr < 0 || addr + len > DeviceConstants.FIRMWARE_SIZE) return false;
     37         for (int i = 0; i < len; i++) {
     38             if (mask[addr + i]) return true;
     39         }
     40         return false;
     41     }
     42 
     43     void getData(byte[] dest, int index, int addr, int count) {
     44         System.arraycopy(image, addr, dest, index, count);
     45     }
     46 
     47     void parseHex(InputStream stream) throws ParseException {
     48         Arrays.fill(image, (byte) 0xFF);
     49         Arrays.fill(mask, false);
     50         BufferedReader in = new BufferedReader(new InputStreamReader(stream));
     51         try {
     52             String line;
     53             while ((line = in.readLine()) != null) {
     54                 parseLine(line);
     55             }
     56         } catch (IOException e) {
     57             Log.e(TAG, "Reading input file: " + e);
     58         }
     59 
     60         if (!atEOF) throw new ParseException("No EOF marker", -1);
     61         Log.d(TAG, "Done parsing file");
     62     }
     63 
     64     private void parseLine(String line) throws ParseException {
     65         if (atEOF) throw new ParseException("Line after EOF marker", -1);
     66         int cur = 0;
     67         final int length = line.length();
     68         if (length < 1 || line.charAt(cur) != ':') {
     69             throw new ParseException("Expected ':', got '" + line.charAt(cur), cur);
     70         }
     71         cur++;
     72 
     73         int count = parseByte(line, cur);
     74         cur += 2;
     75         int addr = parseInt(line, cur);
     76         cur += 4;
     77         byte code = parseByte(line, cur);
     78         cur += 2;
     79 
     80         switch (code) {
     81             case 0x00: {
     82                 parseData(line, cur, count, image, mask, addr);
     83                 // TODO: verify checksum
     84                 break;
     85             }
     86             case 0x01: {
     87                 Log.d(TAG, "Got EOF marker");
     88                 atEOF = true;
     89                 return;
     90             }
     91             default: {
     92                 throw new ParseException(String.format("Unknown code '%x'", code), cur);
     93             }
     94         }
     95     }
     96 
     97     private static byte parseByte(String line, int pos) throws ParseException {
     98         if (line.length() < pos + 2) throw new ParseException("Unexpected EOL", pos);
     99         try {
    100             return (byte) Integer.parseInt(line.substring(pos, pos + 2), 16);
    101         } catch (NumberFormatException e) {
    102             throw new ParseException("Malformed file: " + e.getMessage(), pos);
    103         }
    104     }
    105 
    106     private static int parseInt(String line, int pos) throws ParseException {
    107         if (line.length() < pos + 4) throw new ParseException("Unexpected EOL", pos);
    108         try {
    109             return Integer.parseInt(line.substring(pos, pos + 4), 16);
    110         } catch (NumberFormatException e) {
    111             throw new ParseException("Malformed file: " + e.getMessage(), pos);
    112         }
    113     }
    114 
    115     private static void parseData(String line, int pos, int count,
    116                                   byte[] dest, boolean[] mask, int addr) throws ParseException {
    117         for (int i = 0; i < count; i++) {
    118             try {
    119                 dest[addr + i] = parseByte(line, pos + i * 2);
    120                 mask[addr + i] = true;
    121             } catch (ArrayIndexOutOfBoundsException e) {
    122                 throw new ParseException(String.format("Address '%x' out of range", addr + i),
    123                         pos + i * 2);
    124             }
    125         }
    126     }
    127 }
    128