• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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