1 /*
2  * Copyright (C) 2018 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 #pragma once
17 
18 #include <stdint.h>
19 
20 #include <memory>
21 #include <string>
22 
23 #include "common/libs/fs/shared_fd.h"
24 
25 namespace cvd {
26 
27 // Unpacks the boot image and extracts kernel, ramdisk and kernel arguments
28 class BootImageUnpacker {
29  public:
30   // Reads header section of boot image at path and returns a BootImageUnpacker
31   // preloaded with all the metadata.
32   static std::unique_ptr<BootImageUnpacker> FromImages(
33     const std::string& boot_image_path,
34     const std::string& vendor_boot_image_path);
35 
36   ~BootImageUnpacker() = default;
37 
38   std::string kernel_cmdline() const;
39 
HasKernelImage()40   bool HasKernelImage() const { return kernel_image_size_ > 0; }
HasRamdiskImage()41   bool HasRamdiskImage() const { return ramdisk_image_size_ > 0; }
HasVendorRamdiskImage()42   bool HasVendorRamdiskImage() const { return vendor_ramdisk_image_size_ > 0; }
43 
44   bool Unpack(const std::string& ramdisk_image_path,
45               const std::string& vendor_ramdisk_image_path,
46               const std::string& kernel_image_path);
47 
48  private:
BootImageUnpacker(SharedFD boot_image,const std::string & cmdline,uint32_t kernel_image_size,uint32_t kernel_image_offset,uint32_t ramdisk_image_size,uint32_t ramdisk_image_offset,SharedFD vendor_boot_image,uint32_t vendor_ramdisk_image_size,uint32_t vendor_ramdisk_image_offset)49   BootImageUnpacker(SharedFD boot_image, const std::string& cmdline,
50                     uint32_t kernel_image_size, uint32_t kernel_image_offset,
51                     uint32_t ramdisk_image_size, uint32_t ramdisk_image_offset,
52                     SharedFD vendor_boot_image,
53                     uint32_t vendor_ramdisk_image_size,
54                     uint32_t vendor_ramdisk_image_offset)
55       : boot_image_(boot_image),
56         vendor_boot_image_(vendor_boot_image),
57         kernel_cmdline_(cmdline),
58         kernel_image_size_(kernel_image_size),
59         kernel_image_offset_(kernel_image_offset),
60         ramdisk_image_size_(ramdisk_image_size),
61         ramdisk_image_offset_(ramdisk_image_offset),
62         vendor_ramdisk_image_size_(vendor_ramdisk_image_size),
63         vendor_ramdisk_image_offset_(vendor_ramdisk_image_offset) {}
64 
65   // Mutable because we only read from the fd, but do not modify its contents
66   mutable SharedFD boot_image_;
67   mutable SharedFD vendor_boot_image_;
68   std::string kernel_cmdline_;
69   // When buidling the boot image a particular page size is assumed, which may
70   // not match the actual page size of the system.
71   uint32_t kernel_image_size_;
72   uint32_t kernel_image_offset_;
73   uint32_t ramdisk_image_size_;
74   uint32_t ramdisk_image_offset_;
75   uint32_t vendor_ramdisk_image_size_;
76   uint32_t vendor_ramdisk_image_offset_;
77 
78   // Extracts the kernel image to the given path
79   bool ExtractKernelImage(const std::string& path) const;
80   // Extracts the ramdisk image to the given path. It may return false if the
81   // boot image does not contain a ramdisk, which is the case when having system
82   // as root.
83   bool ExtractRamdiskImage(const std::string& path) const;
84   // Extracts the vendor ramdisk image to the given path
85   bool ExtractVendorRamdiskImage(const std::string& path) const;
86 };
87 
88 }  // namespace cvd
89