1 /* 2 * Copyright (C) 2020 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 package com.android.tests.firmware; 17 18 import java.io.File; 19 import java.io.IOException; 20 import java.io.InputStream; 21 import java.io.RandomAccessFile; 22 import java.nio.ByteBuffer; 23 import java.nio.ByteOrder; 24 import java.util.Arrays; 25 import java.util.Collections; 26 import java.util.List; 27 28 public class BootImageInfo implements AutoCloseable { 29 // Common definitions to all boot header versions. 30 static int KERNEL_SIZE_OFFSET = 2 * 4; 31 static int HOST_IMG_HEADER_VER_OFFSET = 10 * 4; 32 33 // Definitions specific to boot header versions < 3. 34 static int RAMDISK_SIZE_OFFSET = 4 * 4; 35 static int PAGE_SIZE_OFFSET = 9 * 4; 36 // Offset of recovery dtbo size in boot header of version 1. 37 static int BOOT_HEADER_DTBO_SIZE_OFFSET = 1632; 38 static int BOOT_HEADER_SIZE_OFFSET = BOOT_HEADER_DTBO_SIZE_OFFSET + 4 + 8; 39 static int DTB_SIZE_OFFSET = BOOT_HEADER_SIZE_OFFSET + 4; 40 41 // Definitions specific to boot header version 3. 42 static int V3_RAMDISK_SIZE_OFFSET = 3 * 4; 43 static int V3_BOOT_HEADER_SIZE_OFFSET = 5 * 4; 44 static int V3_BOOT_HEADER_SIZE = 1580; 45 46 // Definitions specific to boot header version 4. 47 static int V4_BOOT_HEADER_SIZE = 1584; 48 49 private int mKernelSize = 0; 50 private int mRamdiskSize = 0; 51 private int mPageSize = 0; 52 private int mImgHeaderVer = 0; 53 private int mRecoveryDtboSize = 0; 54 private int mBootHeaderSize = 0; 55 private int mDtbSize = 0; 56 private RandomAccessFile mRaf = null; 57 58 /** 59 * Create a {@link BootImageInfo}. 60 */ BootImageInfo(String imagePath)61 public BootImageInfo(String imagePath) throws IOException { 62 File bootImg = new File(imagePath); 63 mRaf = new RandomAccessFile(bootImg, "r"); 64 byte[] bytes = new byte[4]; 65 66 mRaf.seek(KERNEL_SIZE_OFFSET); 67 mRaf.read(bytes); 68 mKernelSize = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt(); 69 70 mRaf.seek(HOST_IMG_HEADER_VER_OFFSET); 71 mRaf.read(bytes); 72 mImgHeaderVer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt(); 73 74 if (mImgHeaderVer < 3) { 75 mRaf.seek(RAMDISK_SIZE_OFFSET); 76 } else { 77 mRaf.seek(V3_RAMDISK_SIZE_OFFSET); 78 } 79 mRaf.read(bytes); 80 mRamdiskSize = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt(); 81 82 if (mImgHeaderVer < 3) { 83 mRaf.seek(PAGE_SIZE_OFFSET); 84 mRaf.read(bytes); 85 mPageSize = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt(); 86 } else { 87 mPageSize = 4096; 88 } 89 90 if (mImgHeaderVer < 3) { 91 mRaf.seek(BOOT_HEADER_DTBO_SIZE_OFFSET); 92 mRaf.read(bytes); 93 mRecoveryDtboSize = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt(); 94 } else { 95 mRecoveryDtboSize = -1; 96 } 97 98 if (mImgHeaderVer < 3) { 99 mRaf.seek(BOOT_HEADER_SIZE_OFFSET); 100 } else { 101 mRaf.seek(V3_BOOT_HEADER_SIZE_OFFSET); 102 } 103 mRaf.read(bytes); 104 mBootHeaderSize = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt(); 105 106 if (mImgHeaderVer == 2) { 107 mRaf.seek(DTB_SIZE_OFFSET); 108 mRaf.read(bytes); 109 mDtbSize = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt(); 110 } else { 111 mDtbSize = -1; 112 } 113 } 114 115 /** 116 * Get kernel size of boot image. 117 * 118 * @return the value of kernel size. 119 */ getKernelSize()120 public int getKernelSize() { 121 return mKernelSize; 122 } 123 setKernelSize(int size)124 public void setKernelSize(int size) { 125 mKernelSize = size; 126 } 127 128 /** 129 * Get ramdisk size of boot image. 130 * 131 * @return the value of ramdisk size. 132 */ getRamdiskSize()133 public int getRamdiskSize() { 134 return mRamdiskSize; 135 } 136 setRamdiskSize(int size)137 public void setRamdiskSize(int size) { 138 mRamdiskSize = size; 139 } 140 141 /** 142 * Get page size of boot image. 143 * 144 * @return the value of page size. 145 */ getPageSize()146 public int getPageSize() { 147 return mPageSize; 148 } 149 setPageSize(int size)150 public void setPageSize(int size) { 151 mPageSize = size; 152 } 153 154 /** 155 * Get image header version of boot image. 156 * 157 * @return the value of host image header version. 158 */ getImgHeaderVer()159 public int getImgHeaderVer() { 160 return mImgHeaderVer; 161 } 162 setImgHeaderVer(int version)163 public void setImgHeaderVer(int version) { 164 mImgHeaderVer = version; 165 } 166 167 /** 168 * Get recovery dtbo size of boot image. 169 * 170 * @return the value of recovery dtbo size. 171 */ getRecoveryDtboSize()172 public int getRecoveryDtboSize() { 173 return mRecoveryDtboSize; 174 } 175 setRecoveryDtboSize(int size)176 public void setRecoveryDtboSize(int size) { 177 mRecoveryDtboSize = size; 178 } 179 180 /** 181 * Get boot header size of boot image. 182 * 183 * @return the value of boot header size. 184 */ getBootHeaderSize()185 public int getBootHeaderSize() { 186 return mBootHeaderSize; 187 } 188 setBootHeaderSize(int size)189 public void setBootHeaderSize(int size) { 190 mBootHeaderSize = size; 191 } 192 193 /** 194 * Get dtb size of boot image. 195 * 196 * @return the value of dtb size. 197 */ getDtbSize()198 public int getDtbSize() { 199 return mDtbSize; 200 } 201 setDtbSize(int size)202 public void setDtbSize(int size) { 203 mDtbSize = size; 204 } 205 206 /** 207 * Get expect header size of boot image. 208 * 209 * @return the value of expected header size. 210 */ getExpectHeaderSize()211 public int getExpectHeaderSize() { 212 switch (mImgHeaderVer) { 213 case 1: 214 return BOOT_HEADER_SIZE_OFFSET + 4; 215 case 2: 216 return BOOT_HEADER_SIZE_OFFSET + 16; 217 case 3: 218 return V3_BOOT_HEADER_SIZE; 219 case 4: 220 return V4_BOOT_HEADER_SIZE; 221 default: 222 return -1; 223 } 224 } 225 226 /** 227 * Get kernel page numbers of boot image. 228 * 229 * @return the value of kernel page numbers. 230 */ getKernelPageNum()231 int getKernelPageNum() { 232 return (mKernelSize + mPageSize - 1) / mPageSize; 233 } 234 235 /** 236 * Get the content of ramdisk. 237 * 238 * @return the content of ramdisk. 239 */ getRamdiskStream()240 public byte[] getRamdiskStream() throws IOException { 241 byte[] tmpBytes = new byte[mRamdiskSize]; 242 int ramDiskOffset = mPageSize * (1 + getKernelPageNum()); 243 mRaf.seek(ramDiskOffset); 244 mRaf.read(tmpBytes); 245 return tmpBytes; 246 } 247 248 @Override close()249 public void close() throws Exception { 250 if (mRaf != null) { 251 mRaf.close(); 252 } 253 } 254 } 255