mirror of
				https://github.com/Tasssadar/libbootimg.git
				synced 2025-11-04 13:55:44 +08:00 
			
		
		
		
	[0.2.0] Rewrite the whole library
* Rewrite libbootimg to use "blobs" concept - kernel, initrd, second stage and DTB are all objects of same type, which enabled me to make functions shorter (they don't have to deal with each of them individualy). * Move image size and config related functions to bbootimg.c - they should not be in the library. * Document all library functions * Clean-up the API
This commit is contained in:
		@@ -17,6 +17,8 @@
 | 
			
		||||
#ifndef BOOT_IMG_HDR_H
 | 
			
		||||
#define BOOT_IMG_HDR_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** +-----------------+ 
 | 
			
		||||
** | boot header     | 1 page
 | 
			
		||||
@@ -54,27 +56,27 @@
 | 
			
		||||
 | 
			
		||||
struct boot_img_hdr
 | 
			
		||||
{
 | 
			
		||||
    unsigned char magic[BOOT_MAGIC_SIZE];
 | 
			
		||||
    uint8_t magic[BOOT_MAGIC_SIZE];
 | 
			
		||||
 | 
			
		||||
    unsigned kernel_size;  /* size in bytes */
 | 
			
		||||
    unsigned kernel_addr;  /* physical load addr */
 | 
			
		||||
    uint32_t kernel_size;  /* size in bytes */
 | 
			
		||||
    uint32_t kernel_addr;  /* physical load addr */
 | 
			
		||||
 | 
			
		||||
    unsigned ramdisk_size; /* size in bytes */
 | 
			
		||||
    unsigned ramdisk_addr; /* physical load addr */
 | 
			
		||||
    uint32_t ramdisk_size; /* size in bytes */
 | 
			
		||||
    uint32_t ramdisk_addr; /* physical load addr */
 | 
			
		||||
 | 
			
		||||
    unsigned second_size;  /* size in bytes */
 | 
			
		||||
    unsigned second_addr;  /* physical load addr */
 | 
			
		||||
    uint32_t second_size;  /* size in bytes */
 | 
			
		||||
    uint32_t second_addr;  /* physical load addr */
 | 
			
		||||
 | 
			
		||||
    unsigned tags_addr;    /* physical addr for kernel tags */
 | 
			
		||||
    unsigned page_size;    /* flash page size we assume */
 | 
			
		||||
    unsigned dt_size;      /* device tree in bytes */
 | 
			
		||||
    unsigned unused;       /* future expansion: should be 0 */
 | 
			
		||||
    uint32_t tags_addr;    /* physical addr for kernel tags */
 | 
			
		||||
    uint32_t page_size;    /* flash page size we assume */
 | 
			
		||||
    uint32_t dt_size;      /* device tree in bytes */
 | 
			
		||||
    uint32_t unused;       /* future expansion: should be 0 */
 | 
			
		||||
 | 
			
		||||
    unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
 | 
			
		||||
    uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
 | 
			
		||||
 | 
			
		||||
    unsigned char cmdline[BOOT_ARGS_SIZE];
 | 
			
		||||
    uint8_t cmdline[BOOT_ARGS_SIZE];
 | 
			
		||||
 | 
			
		||||
    unsigned id[8]; /* timestamp / checksum / sha1 / etc */
 | 
			
		||||
    uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct boot_img_hdr boot_img_hdr;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * @brief This file contains all public libbootimg methods, defines and structs
 | 
			
		||||
 */
 | 
			
		||||
#ifndef LIBBOOTIMG_H
 | 
			
		||||
#define LIBBOOTIMG_h
 | 
			
		||||
 | 
			
		||||
@@ -6,12 +10,16 @@ extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "boot_img_hdr.h"
 | 
			
		||||
 | 
			
		||||
#define LIBBOOTIMG_VERSION 0x000112 // 0xMMNNPP
 | 
			
		||||
#define LIBBOOTIMG_VERSION_STR "0.1.12"
 | 
			
		||||
#define LIBBOOTIMG_VERSION 0x000200 // 0xMMNNPP
 | 
			
		||||
#define LIBBOOTIMG_VERSION_STR "0.2.0"
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
/**
 | 
			
		||||
 * Enum containing possible blob types in a boot image.
 | 
			
		||||
 */
 | 
			
		||||
enum libbootimg_blob_type
 | 
			
		||||
{
 | 
			
		||||
    LIBBOOTIMG_BLOB_KERNEL  = 0,
 | 
			
		||||
    LIBBOOTIMG_BLOB_RAMDISK = 1,
 | 
			
		||||
@@ -21,66 +29,228 @@ enum
 | 
			
		||||
    LIBBOOTIMG_BLOB_CNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Enum with masks passed to libbootimg_init_load method.
 | 
			
		||||
 * Specifies which parts of boot image to load from disk.
 | 
			
		||||
 */
 | 
			
		||||
enum libbootimg_blob_load_mask
 | 
			
		||||
{
 | 
			
		||||
    LIBBOOTIMG_LOAD_HDR_ONLY    = 0x00,
 | 
			
		||||
 | 
			
		||||
    LIBBOOTIMG_LOAD_KERNEL      = (1 << LIBBOOTIMG_BLOB_KERNEL),
 | 
			
		||||
    LIBBOOTIMG_LOAD_RAMDISK     = (1 << LIBBOOTIMG_BLOB_RAMDISK),
 | 
			
		||||
    LIBBOOTIMG_LOAD_SECOND      = (1 << LIBBOOTIMG_BLOB_SECOND),
 | 
			
		||||
    LIBBOOTIMG_LOAD_DTB         = (1 << LIBBOOTIMG_BLOB_DTB),
 | 
			
		||||
 | 
			
		||||
    LIBBOOTIMG_LOAD_ALL         = ( LIBBOOTIMG_LOAD_KERNEL |
 | 
			
		||||
                                    LIBBOOTIMG_LOAD_RAMDISK |
 | 
			
		||||
                                    LIBBOOTIMG_LOAD_SECOND |
 | 
			
		||||
                                    LIBBOOTIMG_LOAD_DTB )
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Enum with all possible error return values.
 | 
			
		||||
 */
 | 
			
		||||
// Keep libbootimg_error_str updated!
 | 
			
		||||
enum libbootimg_error
 | 
			
		||||
{
 | 
			
		||||
    LIBBOOTIMG_SUCCESS                  =  0,
 | 
			
		||||
    LIBBOOTIMG_ERROR_IO                 = -1,
 | 
			
		||||
    LIBBOOTIMG_ERROR_ACCESS             = -2,
 | 
			
		||||
    LIBBOOTIMG_ERROR_NOT_FOUND          = -3,
 | 
			
		||||
    LIBBOOTIMG_ERROR_INVALID_MAGIC      = -4,
 | 
			
		||||
    LIBBOOTIMG_ERROR_IMG_EOF            = -5,
 | 
			
		||||
    LIBBOOTIMG_ERROR_NO_BLOB_DATA       = -6,
 | 
			
		||||
    LIBBOOTIMG_ERROR_FILE_TOO_BIG       = -7,
 | 
			
		||||
    LIBBOOTIMG_ERROR_MISSING_BLOB       = -8,
 | 
			
		||||
    LIBBOOTIMG_ERROR_INVALID_PAGESIZE   = -9,
 | 
			
		||||
 | 
			
		||||
    LIBBOOTIMG_ERROR_OTHER              = -128
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * One data blob from boot image.
 | 
			
		||||
 */
 | 
			
		||||
struct bootimg_blob
 | 
			
		||||
{
 | 
			
		||||
    uint8_t **data;
 | 
			
		||||
    uint32_t *size;
 | 
			
		||||
    uint8_t *data;
 | 
			
		||||
    uint32_t *size; /*!< Pointer to size of this blob in struct boot_img_hdr. Never change the address this is pointing to! */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Main libbootimg struct with all data.
 | 
			
		||||
 * You will use this struct to work with libbootimg.
 | 
			
		||||
 */
 | 
			
		||||
struct bootimg
 | 
			
		||||
{
 | 
			
		||||
    struct boot_img_hdr hdr;
 | 
			
		||||
    uint8_t *kernel;
 | 
			
		||||
    uint8_t *ramdisk;
 | 
			
		||||
    uint8_t *second;
 | 
			
		||||
    uint8_t *dtb;
 | 
			
		||||
    uint32_t size;
 | 
			
		||||
    int size_is_max_only;
 | 
			
		||||
 | 
			
		||||
    struct bootimg_blob *blobs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// for libbootimg_load_parts
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
    LIBBOOTIMG_LOAD_ONLY_HDR = 0x00,
 | 
			
		||||
 | 
			
		||||
    LIBBOOTIMG_LOAD_KERNEL  = (1 << LIBBOOTIMG_BLOB_KERNEL),
 | 
			
		||||
    LIBBOOTIMG_LOAD_RAMDISK = (1 << LIBBOOTIMG_BLOB_RAMDISK),
 | 
			
		||||
    LIBBOOTIMG_LOAD_SECOND  = (1 << LIBBOOTIMG_BLOB_SECOND),
 | 
			
		||||
    LIBBOOTIMG_LOAD_DTB     = (1 << LIBBOOTIMG_BLOB_DTB),
 | 
			
		||||
 | 
			
		||||
    LIBBOOTIMG_LOAD_ALL     = 0xFFFFFFFF
 | 
			
		||||
    struct boot_img_hdr hdr; /*!< Boot image header */
 | 
			
		||||
    struct bootimg_blob blobs[LIBBOOTIMG_BLOB_CNT]; /*!< Blobs packed in the boot image. */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initializes the struct bootimg and leaves it empty with some default values.
 | 
			
		||||
 * It fills in the magic and default pagesize in struct boot_img_hdr.
 | 
			
		||||
 * @see struct boot_img_hdr
 | 
			
		||||
 * @param img pointer to (uninitialized) struct bootimg
 | 
			
		||||
 */
 | 
			
		||||
void libbootimg_init_new(struct bootimg *img);
 | 
			
		||||
void libbootimg_init_blob_table(struct bootimg *img);
 | 
			
		||||
int libbootimg_init_load(struct bootimg *img, const char *path);
 | 
			
		||||
int libbootimg_init_load_parts(struct bootimg *img, const char *path, int load_blob_mask);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initializes the struct bootimg and loads data into it.
 | 
			
		||||
 * @param img pointer to (uninitialized) struct bootimg
 | 
			
		||||
 * @param path path to boot.img to load data from
 | 
			
		||||
 * @param load_blob_mask mask specifying which parts to load into the bootimg struct
 | 
			
		||||
 * @see enum libbootimg_blob_load_mask
 | 
			
		||||
 * @return Zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_init_load(struct bootimg *img, const char *path, int load_blob_mask);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loads boot_img_hdr from file on disk
 | 
			
		||||
 * @param hdr pointer to boot_img_hdr structure
 | 
			
		||||
 * @param path path to boot.img to load header from
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_load_header(struct boot_img_hdr *hdr, const char *path);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Frees all resources used by this bootimg struct
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 */
 | 
			
		||||
void libbootimg_destroy(struct bootimg *b);
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_kernel(struct bootimg *b, const char *dest);
 | 
			
		||||
int libbootimg_dump_ramdisk(struct bootimg *b, const char *dest);
 | 
			
		||||
int libbootimg_dump_second(struct bootimg *b, const char *dest);
 | 
			
		||||
int libbootimg_dump_dtb(struct bootimg *b, const char *dest);
 | 
			
		||||
int libbootimg_dump(struct bootimg *b, const char *dest_dir);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes blob to a file.
 | 
			
		||||
 * @param blob pointer to source struct bootimg_blob
 | 
			
		||||
 * @param dest path to destination file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_dump_blob(struct bootimg_blob *blob, const char *dest);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes kernel blob to a file.
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param dest path to destination file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_dump_kernel(struct bootimg *b, const char *dest);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes ramdisk blob to a file.
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param dest path to destination file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_dump_ramdisk(struct bootimg *b, const char *dest);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes second stage blob to a file.
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param dest path to destination file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_dump_second(struct bootimg *b, const char *dest);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes DTB blob to a file.
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param dest path to destination file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_dump_dtb(struct bootimg *b, const char *dest);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loads blob data from a file.
 | 
			
		||||
 * @param blob pointer to dest struct bootimg_blob
 | 
			
		||||
 * @param src path to source file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_load_blob(struct bootimg_blob *blob, const char *src);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loads kernel blob data from a file.
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param src path to source file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_load_kernel(struct bootimg *b, const char *src);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loads ramdisk blob data from a file.
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param src path to source file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_load_ramdisk(struct bootimg *b, const char *src);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loads second stage blob data from a file.
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param src path to source file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_load_second(struct bootimg *b, const char *src);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loads DTB blob data from a file.
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param src path to source file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_load_dtb(struct bootimg *b, const char *src);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes boot image to a file
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param dest path to destination file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_write_img(struct bootimg *b, const char *dest);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes boot image to a file
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param f pointer to FILE to write data into
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_write_img_fileptr(struct bootimg *b, FILE *f);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes boot image to a file and then calls libbootimg_destroy.
 | 
			
		||||
 * The bootimg struct is destroyed even if this function fails.
 | 
			
		||||
 * @param b pointer to struct bootimg
 | 
			
		||||
 * @param dest path to destination file
 | 
			
		||||
 * @return zero if successful, negative value from libbootimg_error if failed.
 | 
			
		||||
 */
 | 
			
		||||
int libbootimg_write_img_and_destroy(struct bootimg *b, const char *dest);
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_config(struct bootimg *b, const char *src, int *error_line);
 | 
			
		||||
int libbootimg_load_config_line(struct bootimg *b, char *line);
 | 
			
		||||
int libbootimg_write_config(struct bootimg *b, const char *dst);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns version number, format is 0xMMNNPP, so for version 0.1.12 it would return 0x000112
 | 
			
		||||
 * @return version number in 0xMMNNPP format
 | 
			
		||||
 */
 | 
			
		||||
uint32_t libbootimg_version(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns version string
 | 
			
		||||
 * @return version string, e.g. 0.1.12
 | 
			
		||||
 */
 | 
			
		||||
const char *libbootimg_version_str(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Translates value from enum libbootimg_error to readable string.
 | 
			
		||||
 * @param error value from libbootimg_error
 | 
			
		||||
 * @see enum libbootimg_error
 | 
			
		||||
 * @return readable error string
 | 
			
		||||
 */
 | 
			
		||||
const char *libbootimg_error_str(int error);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										477
									
								
								src/bbootimg.c
									
									
									
									
									
								
							
							
						
						
									
										477
									
								
								src/bbootimg.c
									
									
									
									
									
								
							@@ -2,6 +2,10 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "../include/libbootimg.h"
 | 
			
		||||
 | 
			
		||||
@@ -10,16 +14,30 @@
 | 
			
		||||
#define ACT_UPDATE  2
 | 
			
		||||
#define ACT_CREATE  3
 | 
			
		||||
 | 
			
		||||
static const char *default_fname_cfg = "bootimg.cfg";
 | 
			
		||||
static const char *default_fname_blobs[] = {
 | 
			
		||||
    "zImage",     // LIBBOOTIMG_BLOB_KERNEL
 | 
			
		||||
    "initrd.img", // LIBBOOTIMG_BLOB_RAMDISK
 | 
			
		||||
    "stage2.img", // LIBBOOTIMG_BLOB_SECOND
 | 
			
		||||
    "dtb.img",    // LIBBOOTIMG_BLOB_DTB
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char *blob_names[] = {
 | 
			
		||||
    "kernel",       // LIBBOOTIMG_BLOB_KERNEL
 | 
			
		||||
    "ramdisk",      // LIBBOOTIMG_BLOB_RAMDISK
 | 
			
		||||
    "second stage", // LIBBOOTIMG_BLOB_SECOND
 | 
			
		||||
    "DTB",          // LIBBOOTIMG_BLOB_DTB
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct bbootimg_info
 | 
			
		||||
{
 | 
			
		||||
    struct bootimg img;
 | 
			
		||||
    off_t img_size;
 | 
			
		||||
    int size_is_max_only;
 | 
			
		||||
    int act;
 | 
			
		||||
    char *fname_img;
 | 
			
		||||
    char *fname_kernel;
 | 
			
		||||
    char *fname_ramdisk;
 | 
			
		||||
    char *fname_second;
 | 
			
		||||
    char *fname_dtb;
 | 
			
		||||
    char *fname_cfg;
 | 
			
		||||
    const char *fname_img;
 | 
			
		||||
    const char *fname_cfg;
 | 
			
		||||
    const char *fname_blobs[LIBBOOTIMG_BLOB_CNT];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void print_help(const char *prog_name)
 | 
			
		||||
@@ -35,7 +53,7 @@ static void print_help(const char *prog_name)
 | 
			
		||||
    "\n"
 | 
			
		||||
    "%s -j <bootimg>    - print image information in JSON\n"
 | 
			
		||||
    "\n"
 | 
			
		||||
    "%s -x <bootimg> [<bootimg.cfg> [<kernel> [<ramdisk> [<secondstage>]]]]\n"
 | 
			
		||||
    "%s -x <bootimg> [<bootimg.cfg> [<kernel> [<ramdisk> [<secondstage> [<dtb>]]]]]\n"
 | 
			
		||||
    "    extract objects from boot image:\n"
 | 
			
		||||
    "    - config file (bootimg.cfg)\n"
 | 
			
		||||
    "    - kernel image (zImage)\n"
 | 
			
		||||
@@ -69,17 +87,200 @@ static void print_help(const char *prog_name)
 | 
			
		||||
    ,libbootimg_version_str(), prog_name, prog_name, prog_name, prog_name, prog_name, prog_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int print_info(const char *path)
 | 
			
		||||
 | 
			
		||||
static int write_config(struct bbootimg_info *i, const char *dst)
 | 
			
		||||
{
 | 
			
		||||
    struct bootimg img;
 | 
			
		||||
    int res = libbootimg_init_load_parts(&img, path, LIBBOOTIMG_LOAD_ONLY_HDR);
 | 
			
		||||
    int res;
 | 
			
		||||
    FILE *f;
 | 
			
		||||
 | 
			
		||||
    f = fopen(dst, "w");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return -errno;
 | 
			
		||||
 | 
			
		||||
    res = fprintf(f,
 | 
			
		||||
        "bootsize = 0x%X\n"
 | 
			
		||||
        "pagesize = 0x%X\n"
 | 
			
		||||
        "kerneladdr = 0x%X\n"
 | 
			
		||||
        "ramdiskaddr = 0x%X\n"
 | 
			
		||||
        "secondaddr = 0x%X\n"
 | 
			
		||||
        "tagsaddr = 0x%X\n"
 | 
			
		||||
        "name = %s\n"
 | 
			
		||||
        "cmdline = %s\n",
 | 
			
		||||
        (uint32_t)i->img_size, i->img.hdr.page_size, i->img.hdr.kernel_addr, i->img.hdr.ramdisk_addr,
 | 
			
		||||
        i->img.hdr.second_addr, i->img.hdr.tags_addr, i->img.hdr.name, i->img.hdr.cmdline);
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void parse_config_str(char *dest, const char *arg_start, const char *arg_end, size_t maxlen)
 | 
			
		||||
{
 | 
			
		||||
    size_t len = 0;
 | 
			
		||||
 | 
			
		||||
    if(*arg_start)
 | 
			
		||||
    {
 | 
			
		||||
        maxlen -= 1; // it includes the NULL
 | 
			
		||||
 | 
			
		||||
        len = arg_end - arg_start;
 | 
			
		||||
        if(len > maxlen)
 | 
			
		||||
            len = maxlen;
 | 
			
		||||
 | 
			
		||||
        strncpy(dest, arg_start, len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dest[len] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int load_config_line(struct bbootimg_info *i, const char *line)
 | 
			
		||||
{
 | 
			
		||||
    const char *start, *end;
 | 
			
		||||
    char *name_e;
 | 
			
		||||
    char *arg_s;
 | 
			
		||||
    size_t n_to_cmp, len;
 | 
			
		||||
 | 
			
		||||
    for(start = line; isspace(*start); ++start);
 | 
			
		||||
 | 
			
		||||
    for(end = start+strlen(start); isspace(*(end-1)); --end);
 | 
			
		||||
 | 
			
		||||
    if(*start == 0 || (name_e = strchr(start, '=')) == NULL)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    arg_s = name_e+1;
 | 
			
		||||
 | 
			
		||||
    for(; isspace(*(name_e-1)) && name_e > start; --name_e);
 | 
			
		||||
    for(; isspace(*arg_s); ++arg_s);
 | 
			
		||||
 | 
			
		||||
    n_to_cmp = name_e - start;
 | 
			
		||||
 | 
			
		||||
    if(strncmp("bootsize", start, n_to_cmp) == 0)
 | 
			
		||||
        i->img_size = strtoll(arg_s, NULL, 0);
 | 
			
		||||
    else if(strncmp("pagesize", start, n_to_cmp) == 0)
 | 
			
		||||
        i->img.hdr.page_size = strtoll(arg_s, NULL, 0);
 | 
			
		||||
    else if(strncmp("kerneladdr", start, n_to_cmp) == 0)
 | 
			
		||||
        i->img.hdr.kernel_addr = strtoll(arg_s, NULL, 0);
 | 
			
		||||
    else if(strncmp("ramdiskaddr", start, n_to_cmp) == 0)
 | 
			
		||||
        i->img.hdr.ramdisk_addr = strtoll(arg_s, NULL, 0);
 | 
			
		||||
    else if(strncmp("secondaddr", start, n_to_cmp) == 0)
 | 
			
		||||
        i->img.hdr.second_addr = strtoll(arg_s, NULL, 0);
 | 
			
		||||
    else if(strncmp("tagsaddr", start, n_to_cmp) == 0)
 | 
			
		||||
        i->img.hdr.tags_addr = strtoll(arg_s, NULL, 0);
 | 
			
		||||
    else if(strncmp("name", start, n_to_cmp) == 0)
 | 
			
		||||
        parse_config_str((char*)i->img.hdr.name, arg_s, end, BOOT_NAME_SIZE);
 | 
			
		||||
    else if(strncmp("cmdline", start, n_to_cmp) == 0)
 | 
			
		||||
        parse_config_str((char*)i->img.hdr.cmdline, arg_s, end, BOOT_ARGS_SIZE);
 | 
			
		||||
    else
 | 
			
		||||
        return -1;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int load_config(struct bbootimg_info *i, const char *src, int *error_line)
 | 
			
		||||
{
 | 
			
		||||
    FILE *f;
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    int line_num = 0;
 | 
			
		||||
    char line[1024];
 | 
			
		||||
 | 
			
		||||
    f = fopen(src, "r");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return -errno;
 | 
			
		||||
 | 
			
		||||
    while(fgets(line, sizeof(line), f))
 | 
			
		||||
    {
 | 
			
		||||
        if(load_config_line(i, line) < 0)
 | 
			
		||||
        {
 | 
			
		||||
            res = -1;
 | 
			
		||||
            if(error_line)
 | 
			
		||||
                *error_line = line_num;
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
        ++line_num;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int load_bootimg(struct bootimg *b, const char *path)
 | 
			
		||||
{
 | 
			
		||||
    int res = libbootimg_init_load(b, path, LIBBOOTIMG_LOAD_ALL);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to load bootimg \"%s\" (%s)!\n", path, strerror(-res));
 | 
			
		||||
        fprintf(stderr, "Failed to load boot image (%s)!", libbootimg_error_str(res));
 | 
			
		||||
        return -res;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static off_t get_bootimg_size(const char *path)
 | 
			
		||||
{
 | 
			
		||||
    struct stat info;
 | 
			
		||||
    if(stat(path, &info) < 0)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to get boot image size (%s)!", strerror(errno));
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If this is a block device, stat will report zero size.
 | 
			
		||||
    // abootimg uses libblkid to get the correct size, but
 | 
			
		||||
    // I don't wanna drag in any dependencies.
 | 
			
		||||
    if(info.st_size == 0)
 | 
			
		||||
    {
 | 
			
		||||
        off_t size;
 | 
			
		||||
        FILE *f;
 | 
			
		||||
 | 
			
		||||
        f = fopen(path, "r");
 | 
			
		||||
        if(!f)
 | 
			
		||||
        {
 | 
			
		||||
            fprintf(stderr, "Failed to get boot image size (%s)!", strerror(errno));
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fseek(f, 0, SEEK_END);
 | 
			
		||||
        size = ftell(f);
 | 
			
		||||
        fclose(f);
 | 
			
		||||
 | 
			
		||||
        if(size <= 0)
 | 
			
		||||
        {
 | 
			
		||||
            fprintf(stderr, "Failed to get boot image size (fseek -> ftell failed, %s)!", strerror(errno));
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        return size;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        return info.st_size;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void load_default_filenames(struct bbootimg_info *i)
 | 
			
		||||
{
 | 
			
		||||
    int x;
 | 
			
		||||
 | 
			
		||||
    i->fname_cfg = default_fname_cfg;
 | 
			
		||||
 | 
			
		||||
    for(x = 0; x < LIBBOOTIMG_BLOB_CNT; ++x)
 | 
			
		||||
        i->fname_blobs[x] = default_fname_blobs[x];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int print_info(const char *path)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    int res;
 | 
			
		||||
    off_t size;
 | 
			
		||||
    struct bootimg img;
 | 
			
		||||
    char name[BOOT_NAME_SIZE+1];
 | 
			
		||||
 | 
			
		||||
    res = libbootimg_init_load(&img, path, LIBBOOTIMG_LOAD_HDR_ONLY);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to load bootimg \"%s\" (%s)!\n", path, libbootimg_error_str(res));
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char name[BOOT_NAME_SIZE+1];
 | 
			
		||||
    if((size = get_bootimg_size(path)) < 0)
 | 
			
		||||
        return 1;
 | 
			
		||||
 | 
			
		||||
    snprintf(name, sizeof(name), "%s", img.hdr.name);
 | 
			
		||||
 | 
			
		||||
    img.hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;
 | 
			
		||||
@@ -87,7 +288,7 @@ static int print_info(const char *path)
 | 
			
		||||
    printf ("\nAndroid Boot Image Info:\n\n");
 | 
			
		||||
    printf ("* file name = %s\n\n", path);
 | 
			
		||||
 | 
			
		||||
    printf ("* image size = %u bytes (%.2f MB)\n", img.size, (double)img.size/0x100000);
 | 
			
		||||
    printf ("* image size = %ld bytes (%.2f MB)\n", size, (double)size/0x100000);
 | 
			
		||||
    printf ("  page size  = %u bytes\n\n", img.hdr.page_size);
 | 
			
		||||
 | 
			
		||||
    printf ("* Boot Name = \"%s\"\n\n", name);
 | 
			
		||||
@@ -112,8 +313,7 @@ static int print_info(const char *path)
 | 
			
		||||
        printf ("* empty cmdline\n");
 | 
			
		||||
 | 
			
		||||
    printf ("* id = ");
 | 
			
		||||
    int i;
 | 
			
		||||
    for (i=0; i<8; i++)
 | 
			
		||||
    for (i = 0; i < 8; ++i)
 | 
			
		||||
        printf ("0x%08x ", img.hdr.id[i]);
 | 
			
		||||
    printf ("\n\n");
 | 
			
		||||
 | 
			
		||||
@@ -123,23 +323,29 @@ static int print_info(const char *path)
 | 
			
		||||
 | 
			
		||||
static int print_json(const char *path)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    int res;
 | 
			
		||||
    off_t size;
 | 
			
		||||
    struct bootimg img;
 | 
			
		||||
    int res = libbootimg_init_load_parts(&img, path, LIBBOOTIMG_LOAD_ONLY_HDR);
 | 
			
		||||
    char name[BOOT_NAME_SIZE+1];
 | 
			
		||||
 | 
			
		||||
    res = libbootimg_init_load(&img, path, LIBBOOTIMG_LOAD_HDR_ONLY);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to load bootimg \"%s\" (%s)!\n", path, strerror(-res));
 | 
			
		||||
        fprintf(stderr, "Failed to load bootimg \"%s\" (%s)!\n", path, libbootimg_error_str(res));
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
    char name[BOOT_NAME_SIZE+1];
 | 
			
		||||
    if((size = get_bootimg_size(path)) < 0)
 | 
			
		||||
        return 1;
 | 
			
		||||
 | 
			
		||||
    snprintf(name, sizeof(name), "%s", img.hdr.name);
 | 
			
		||||
 | 
			
		||||
    img.hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;
 | 
			
		||||
 | 
			
		||||
    printf("{\n");
 | 
			
		||||
    printf("    \"bbootimg_version\": %u,\n", libbootimg_version());
 | 
			
		||||
    printf("    \"img_size\": %u,\n", img.size);
 | 
			
		||||
    printf("    \"img_size\": %ld,\n", size);
 | 
			
		||||
    printf("    \"boot_img_hdr\": {\n");
 | 
			
		||||
    printf("        \"kernel_size\": %u,\n", img.hdr.kernel_size);
 | 
			
		||||
    printf("        \"kernel_addr\": %u,\n", img.hdr.kernel_addr);
 | 
			
		||||
@@ -165,61 +371,41 @@ static int print_json(const char *path)
 | 
			
		||||
 | 
			
		||||
static int extract_bootimg(struct bbootimg_info *i)
 | 
			
		||||
{
 | 
			
		||||
    int res = libbootimg_init_load(&i->img, i->fname_img);
 | 
			
		||||
    int x;
 | 
			
		||||
    int res;
 | 
			
		||||
    struct bootimg_blob *blob;
 | 
			
		||||
 | 
			
		||||
    res = libbootimg_init_load(&i->img, i->fname_img, LIBBOOTIMG_LOAD_ALL);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to load boot image (%s)!\n", strerror(-res));
 | 
			
		||||
        fprintf(stderr, "Failed to load boot image (%s)!\n", libbootimg_error_str(res));
 | 
			
		||||
        return -res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const char *cfg = i->fname_cfg ? i->fname_cfg : "bootimg.cfg";
 | 
			
		||||
    printf("writing boot image config in %s\n", cfg);
 | 
			
		||||
    res = libbootimg_write_config(&i->img, cfg);
 | 
			
		||||
    if((i->img_size = get_bootimg_size(i->fname_img)) < 0)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    printf("writing boot image config in %s\n", i->fname_cfg);
 | 
			
		||||
    res = write_config(i, i->fname_cfg);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to write bootimg cfg (%s)!\n", strerror(-res));
 | 
			
		||||
        return -res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const char *kernel = i->fname_kernel ? i->fname_kernel : "zImage";
 | 
			
		||||
    printf("extracting kernel in %s\n", kernel);
 | 
			
		||||
    res = libbootimg_dump_kernel(&i->img, kernel);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    for(x = 0; x < LIBBOOTIMG_BLOB_CNT; ++x)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to extract kernel (%s)!\n", strerror(-res));
 | 
			
		||||
        return -res;
 | 
			
		||||
    }
 | 
			
		||||
        blob = &i->img.blobs[x];
 | 
			
		||||
 | 
			
		||||
    const char *ramdisk = i->fname_ramdisk ? i->fname_ramdisk : "initrd.img";
 | 
			
		||||
    printf("extracting ramdisk in %s\n", ramdisk);
 | 
			
		||||
    res = libbootimg_dump_ramdisk(&i->img, ramdisk);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to extract ramdisk (%s)!\n", strerror(-res));
 | 
			
		||||
        return -res;
 | 
			
		||||
    }
 | 
			
		||||
        if(*blob->size == 0)
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
    if(i->img.hdr.second_size > 0)
 | 
			
		||||
    {
 | 
			
		||||
        const char *second = i->fname_second ? i->fname_second : "stage2.img";
 | 
			
		||||
        printf("extracting second stage in %s\n", second);
 | 
			
		||||
        res = libbootimg_dump_second(&i->img, second);
 | 
			
		||||
        printf("extracting %s in %s\n", blob_names[x], i->fname_blobs[x]);
 | 
			
		||||
        res = libbootimg_dump_blob(blob, i->fname_blobs[x]);
 | 
			
		||||
        if(res < 0)
 | 
			
		||||
        {
 | 
			
		||||
            fprintf(stderr, "Failed to extract second stage (%s)!\n", strerror(-res));
 | 
			
		||||
            return -res;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(i->img.hdr.dt_size > 0)
 | 
			
		||||
    {
 | 
			
		||||
        const char *dtb = i->fname_dtb ? i->fname_dtb : "dtb.img";
 | 
			
		||||
        printf("extracting DTB in %s\n", dtb);
 | 
			
		||||
        res = libbootimg_dump_dtb(&i->img, dtb);
 | 
			
		||||
        if(res < 0)
 | 
			
		||||
        {
 | 
			
		||||
            fprintf(stderr, "Failed to extract DTB (%s)!\n", strerror(-res));
 | 
			
		||||
            return -res;
 | 
			
		||||
            fprintf(stderr, "Failed to extract %s (%s)!\n", blob_names[x], libbootimg_error_str(res));
 | 
			
		||||
            return res;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -227,33 +413,28 @@ static int extract_bootimg(struct bbootimg_info *i)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int copy_file(const char *src, const char *dst)
 | 
			
		||||
static int copy_file(FILE *in, const char *dst)
 | 
			
		||||
{
 | 
			
		||||
    FILE *in = fopen(src, "r");
 | 
			
		||||
    if(!in)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to open src file!\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
#define CPY_BUFF_SIZE (512*1024)
 | 
			
		||||
    FILE *out;
 | 
			
		||||
    int res = -1;
 | 
			
		||||
    size_t read;
 | 
			
		||||
    char *buff = NULL;
 | 
			
		||||
 | 
			
		||||
    FILE *out = fopen(dst, "w");
 | 
			
		||||
    out = fopen(dst, "w");
 | 
			
		||||
    if(!out)
 | 
			
		||||
    {
 | 
			
		||||
        fclose(in);
 | 
			
		||||
        fprintf(stderr, "Failed to open dst file!\n");
 | 
			
		||||
        fprintf(stderr, "Failed to open dst file (%s)!\n", strerror(errno));
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int res = -1;
 | 
			
		||||
#define BUFF_SIZE (512*1024)
 | 
			
		||||
    char *buff = malloc(BUFF_SIZE);
 | 
			
		||||
    size_t read;
 | 
			
		||||
    buff = malloc(CPY_BUFF_SIZE);
 | 
			
		||||
 | 
			
		||||
    while((read = fread(buff, 1, BUFF_SIZE, in)) > 0)
 | 
			
		||||
    while((read = fread(buff, 1, CPY_BUFF_SIZE, in)) > 0)
 | 
			
		||||
    {
 | 
			
		||||
        if(fwrite(buff, 1, read, out) != read)
 | 
			
		||||
        {
 | 
			
		||||
            fprintf(stderr, "Failed to write data to dst file!\n");
 | 
			
		||||
            fprintf(stderr, "Failed to write data to dst file (%s)!\n", strerror(errno));
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -261,80 +442,69 @@ static int copy_file(const char *src, const char *dst)
 | 
			
		||||
    res = 0;
 | 
			
		||||
exit:
 | 
			
		||||
    free(buff);
 | 
			
		||||
    fclose(in);
 | 
			
		||||
    fclose(out);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int update_bootimg(struct bbootimg_info *i)
 | 
			
		||||
{
 | 
			
		||||
    int x;
 | 
			
		||||
    int res = -1;
 | 
			
		||||
    char *tmpname = malloc(strlen(i->fname_img)+sizeof(".new"));
 | 
			
		||||
    strcpy(tmpname, i->fname_img);
 | 
			
		||||
    strcat(tmpname, ".new");
 | 
			
		||||
    FILE *tmp = NULL;
 | 
			
		||||
    struct bootimg_blob *blob;
 | 
			
		||||
 | 
			
		||||
    if(i->fname_kernel)
 | 
			
		||||
    for(x = 0; x < LIBBOOTIMG_BLOB_CNT; ++x)
 | 
			
		||||
    {
 | 
			
		||||
        printf("reading kernel from %s\n", i->fname_kernel);
 | 
			
		||||
        res = libbootimg_load_kernel(&i->img, i->fname_kernel);
 | 
			
		||||
        if(!i->fname_blobs[x])
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        blob = &i->img.blobs[x];
 | 
			
		||||
 | 
			
		||||
        printf("reading %s from %s\n", blob_names[x], i->fname_blobs[x]);
 | 
			
		||||
        res = libbootimg_load_blob(blob, i->fname_blobs[x]);
 | 
			
		||||
        if(res < 0)
 | 
			
		||||
        {
 | 
			
		||||
            res = -res;
 | 
			
		||||
            fprintf(stderr, "Failed to load kernel (%s)!\n", strerror(res));
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(i->fname_ramdisk)
 | 
			
		||||
    {
 | 
			
		||||
        printf("reading ramdisk from %s\n", i->fname_ramdisk);
 | 
			
		||||
        res = libbootimg_load_ramdisk(&i->img, i->fname_ramdisk);
 | 
			
		||||
        if(res < 0)
 | 
			
		||||
        {
 | 
			
		||||
            res = -res;
 | 
			
		||||
            fprintf(stderr, "Failed to load ramdisk (%s)!\n", strerror(res));
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(i->fname_second)
 | 
			
		||||
    {
 | 
			
		||||
        printf("reading second stage from %s\n", i->fname_second);
 | 
			
		||||
        res = libbootimg_load_second(&i->img, i->fname_second);
 | 
			
		||||
        if(res < 0)
 | 
			
		||||
        {
 | 
			
		||||
            res = -res;
 | 
			
		||||
            fprintf(stderr, "Failed to load second stage (%s)!\n", strerror(res));
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(i->fname_dtb)
 | 
			
		||||
    {
 | 
			
		||||
        printf("reading device tree blob from %s\n", i->fname_dtb);
 | 
			
		||||
        res = libbootimg_load_dtb(&i->img, i->fname_dtb);
 | 
			
		||||
        if(res < 0)
 | 
			
		||||
        {
 | 
			
		||||
            res = -res;
 | 
			
		||||
            fprintf(stderr, "Failed to load device tree blob (%s)!\n", strerror(res));
 | 
			
		||||
            fprintf(stderr, "Failed to load %s (%s)!\n", blob_names[x], libbootimg_error_str(res));
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("Writing Boot Image %s\n", i->fname_img);
 | 
			
		||||
    res = libbootimg_write_img(&i->img, tmpname);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
 | 
			
		||||
    tmp = tmpfile();
 | 
			
		||||
    if(!tmp)
 | 
			
		||||
    {
 | 
			
		||||
        res = -res;
 | 
			
		||||
        fprintf(stderr, "Failed to create boot image (%s)!\n", strerror(res));
 | 
			
		||||
        fprintf(stderr, "Failed to create tmp file (%s)!\n", strerror(errno));
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    copy_file(tmpname, i->fname_img);
 | 
			
		||||
    res = libbootimg_write_img_fileptr(&i->img, tmp);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to create boot image (%s)!\n", libbootimg_error_str(res));
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // bootimg size (abootimg compatibility)
 | 
			
		||||
    if(i->img_size != 0)
 | 
			
		||||
    {
 | 
			
		||||
        if(i->img_size < ftell(tmp))
 | 
			
		||||
        {
 | 
			
		||||
            fprintf(stderr, "Failed to create boot image: the result image is too big\n");
 | 
			
		||||
            res = -1;
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(i->size_is_max_only == 0)
 | 
			
		||||
            ftruncate(fileno(tmp), i->img_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rewind(tmp);
 | 
			
		||||
    copy_file(tmp, i->fname_img);
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    remove(tmpname);
 | 
			
		||||
    free(tmpname);
 | 
			
		||||
    if(tmp)
 | 
			
		||||
        fclose(tmp);
 | 
			
		||||
    libbootimg_destroy(&i->img);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
@@ -349,7 +519,7 @@ static int execute_action(struct bbootimg_info *i)
 | 
			
		||||
            return update_bootimg(i);
 | 
			
		||||
        case ACT_CREATE:
 | 
			
		||||
        {
 | 
			
		||||
            if(!i->fname_kernel || !i->fname_ramdisk)
 | 
			
		||||
            if(!i->fname_blobs[LIBBOOTIMG_BLOB_KERNEL] || !i->fname_blobs[LIBBOOTIMG_BLOB_RAMDISK])
 | 
			
		||||
            {
 | 
			
		||||
                fprintf(stderr, "You have to specify both ramdisk and kernel to create boot image!\n");
 | 
			
		||||
                return EINVAL;
 | 
			
		||||
@@ -360,18 +530,7 @@ static int execute_action(struct bbootimg_info *i)
 | 
			
		||||
    return EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int load_bootimg(struct bootimg *b, const char *path)
 | 
			
		||||
{
 | 
			
		||||
    int res = libbootimg_init_load(b, path);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr, "Failed to load boot image (%s)!", strerror(-res));
 | 
			
		||||
        return -res;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
int main(int argc, const char *argv[])
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
@@ -389,7 +548,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(strcmp("-m", argv[i]) == 0)
 | 
			
		||||
            info.img.size_is_max_only = 1;
 | 
			
		||||
            info.size_is_max_only = 1;
 | 
			
		||||
 | 
			
		||||
        if(i+1 >= argc)
 | 
			
		||||
            continue;
 | 
			
		||||
@@ -402,27 +561,31 @@ int main(int argc, char *argv[])
 | 
			
		||||
        // actions
 | 
			
		||||
        if(strcmp("-x", argv[i]) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            int blob_itr;
 | 
			
		||||
 | 
			
		||||
            load_default_filenames(&info);
 | 
			
		||||
 | 
			
		||||
            info.act = ACT_EXTRACT;
 | 
			
		||||
            info.fname_img = argv[++i];
 | 
			
		||||
 | 
			
		||||
            if(++i < argc)
 | 
			
		||||
                info.fname_cfg = argv[i];
 | 
			
		||||
            if(++i < argc)
 | 
			
		||||
                info.fname_kernel = argv[i];
 | 
			
		||||
            if(++i < argc)
 | 
			
		||||
                info.fname_ramdisk = argv[i];
 | 
			
		||||
            if(++i < argc)
 | 
			
		||||
                info.fname_second = argv[i];
 | 
			
		||||
            if(++i < argc)
 | 
			
		||||
                info.fname_dtb = argv[i];
 | 
			
		||||
 | 
			
		||||
            for(blob_itr = 0; ++i < argc && blob_itr < LIBBOOTIMG_BLOB_CNT; ++blob_itr)
 | 
			
		||||
                info.fname_blobs[blob_itr] = argv[i];
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        else if(strcmp("-u", argv[i]) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            info.act = ACT_UPDATE;
 | 
			
		||||
            info.fname_img = argv[++i];
 | 
			
		||||
            if(load_bootimg(&info.img, info.fname_img) != 0)
 | 
			
		||||
 | 
			
		||||
            if (load_bootimg(&info.img, info.fname_img) != 0)
 | 
			
		||||
               return -1;
 | 
			
		||||
 | 
			
		||||
            if((info.img_size = get_bootimg_size(info.fname_img)) < 0)
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
        else if(strcmp("--create", argv[i]) == 0)
 | 
			
		||||
        {
 | 
			
		||||
@@ -432,7 +595,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
        // params
 | 
			
		||||
        else if(strcmp("-c", argv[i]) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            if(libbootimg_load_config_line(&info.img, argv[++i]) < 0)
 | 
			
		||||
            if(load_config_line(&info, argv[++i]) < 0)
 | 
			
		||||
            {
 | 
			
		||||
                fprintf(stderr, "Invalid config option \"%s\"\n\n", argv[i]);
 | 
			
		||||
                goto exit_help;
 | 
			
		||||
@@ -444,7 +607,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
            printf("reading config file %s\n", info.fname_cfg);
 | 
			
		||||
 | 
			
		||||
            int line = -1;
 | 
			
		||||
            int res = libbootimg_load_config(&info.img, info.fname_cfg, &line);
 | 
			
		||||
            int res = load_config(&info, info.fname_cfg, &line);
 | 
			
		||||
            if(res < 0)
 | 
			
		||||
            {
 | 
			
		||||
                res = -res;
 | 
			
		||||
@@ -453,13 +616,13 @@ int main(int argc, char *argv[])
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if(strcmp("-k", argv[i]) == 0)
 | 
			
		||||
            info.fname_kernel = argv[++i];
 | 
			
		||||
            info.fname_blobs[LIBBOOTIMG_BLOB_KERNEL] = argv[++i];
 | 
			
		||||
        else if(strcmp("-r", argv[i]) == 0)
 | 
			
		||||
            info.fname_ramdisk = argv[++i];
 | 
			
		||||
            info.fname_blobs[LIBBOOTIMG_BLOB_RAMDISK] = argv[++i];
 | 
			
		||||
        else if(strcmp("-s", argv[i]) == 0)
 | 
			
		||||
            info.fname_second = argv[++i];
 | 
			
		||||
            info.fname_blobs[LIBBOOTIMG_BLOB_SECOND] = argv[++i];
 | 
			
		||||
        else if(strcmp("-d", argv[i]) == 0)
 | 
			
		||||
            info.fname_dtb = argv[++i];
 | 
			
		||||
            info.fname_blobs[LIBBOOTIMG_BLOB_DTB] = argv[++i];
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            fprintf(stderr, "Unknown argument: %s\n\n", argv[i]);
 | 
			
		||||
@@ -468,7 +631,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(info.act != ACT_HELP)
 | 
			
		||||
        return execute_action(&info);
 | 
			
		||||
        return execute_action(&info) == 0 ? 0 : 1;
 | 
			
		||||
 | 
			
		||||
exit_help:
 | 
			
		||||
    print_help(argv[0]);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										699
									
								
								src/libbootimg.c
									
									
									
									
									
								
							
							
						
						
									
										699
									
								
								src/libbootimg.c
									
									
									
									
									
								
							@@ -6,286 +6,44 @@
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include "../include/libbootimg.h"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_PAGE_SIZE 2048
 | 
			
		||||
#define MAX_PATH_LEN 4096
 | 
			
		||||
 | 
			
		||||
static inline unsigned align_size(unsigned size, unsigned page_size)
 | 
			
		||||
{
 | 
			
		||||
    return ((size + page_size - 1)/page_size)*page_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void libbootimg_init_new(struct bootimg *img)
 | 
			
		||||
static int translate_errnum(int errnum)
 | 
			
		||||
{
 | 
			
		||||
    memset(img, 0, sizeof(struct bootimg));
 | 
			
		||||
    memcpy(img->hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
 | 
			
		||||
    img->hdr.page_size = DEFAULT_PAGE_SIZE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void libbootimg_init_blob_table(struct bootimg *img)
 | 
			
		||||
{
 | 
			
		||||
    if(img->blobs)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    img->blobs = calloc(LIBBOOTIMG_BLOB_CNT, sizeof(struct bootimg_blob));
 | 
			
		||||
 | 
			
		||||
#define ADD_BLOB(i, d, s) \
 | 
			
		||||
    img->blobs[i].data = &d; \
 | 
			
		||||
    img->blobs[i].size = &s;
 | 
			
		||||
 | 
			
		||||
    ADD_BLOB(LIBBOOTIMG_BLOB_KERNEL,  img->kernel,  img->hdr.kernel_size)
 | 
			
		||||
    ADD_BLOB(LIBBOOTIMG_BLOB_RAMDISK, img->ramdisk, img->hdr.ramdisk_size)
 | 
			
		||||
    ADD_BLOB(LIBBOOTIMG_BLOB_SECOND,  img->second,  img->hdr.second_size)
 | 
			
		||||
    ADD_BLOB(LIBBOOTIMG_BLOB_DTB,     img->dtb,     img->hdr.dt_size)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_init_load(struct bootimg *img, const char *path)
 | 
			
		||||
{
 | 
			
		||||
    return libbootimg_init_load_parts(img, path, LIBBOOTIMG_LOAD_ALL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_init_load_parts(struct bootimg *img, const char *path, int load_blob_mask)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    FILE *f;
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    long long addr;
 | 
			
		||||
 | 
			
		||||
    libbootimg_init_new(img);
 | 
			
		||||
 | 
			
		||||
    res = libbootimg_load_header(&img->hdr, path);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    switch(errno)
 | 
			
		||||
    {
 | 
			
		||||
        libbootimg_destroy(img);
 | 
			
		||||
        return res;
 | 
			
		||||
        case EIO:     return LIBBOOTIMG_ERROR_IO;
 | 
			
		||||
        case EACCES:  return LIBBOOTIMG_ERROR_ACCESS;
 | 
			
		||||
        case ENOENT:  return LIBBOOTIMG_ERROR_NOT_FOUND;
 | 
			
		||||
 | 
			
		||||
        default:      return LIBBOOTIMG_ERROR_OTHER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    libbootimg_init_blob_table(img);
 | 
			
		||||
 | 
			
		||||
    f = fopen(path, "r");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return -errno;
 | 
			
		||||
 | 
			
		||||
    addr = img->hdr.page_size;
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < LIBBOOTIMG_BLOB_CNT; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        if((load_blob_mask & (1 << i)) && *img->blobs[i].size != 0)
 | 
			
		||||
        {
 | 
			
		||||
            *img->blobs[i].data = malloc(*img->blobs[i].size);
 | 
			
		||||
 | 
			
		||||
            if(fseek(f, addr, SEEK_SET) < 0)
 | 
			
		||||
                goto fail_errno;
 | 
			
		||||
 | 
			
		||||
            if(fread(*img->blobs[i].data, *img->blobs[i].size, 1, f) != 1)
 | 
			
		||||
            {
 | 
			
		||||
                if(feof(f))
 | 
			
		||||
                {
 | 
			
		||||
                    res = -EINVAL;
 | 
			
		||||
                    goto fail;
 | 
			
		||||
                }
 | 
			
		||||
                else // IO error
 | 
			
		||||
                {
 | 
			
		||||
                    res = -EIO;
 | 
			
		||||
                    goto fail;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        addr += align_size(*img->blobs[i].size, img->hdr.page_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fseek(f, 0, SEEK_END);
 | 
			
		||||
    img->size = ftell(f);
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return 0;
 | 
			
		||||
fail_errno:
 | 
			
		||||
    res = -errno;
 | 
			
		||||
fail:
 | 
			
		||||
    libbootimg_destroy(img);
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void libbootimg_destroy(struct bootimg *b)
 | 
			
		||||
static int translate_fread_error(FILE *f)
 | 
			
		||||
{
 | 
			
		||||
    free(b->kernel);
 | 
			
		||||
    free(b->ramdisk);
 | 
			
		||||
    free(b->second);
 | 
			
		||||
    free(b->dtb);
 | 
			
		||||
 | 
			
		||||
    b->kernel = b->ramdisk = b->second = b->dtb = NULL;
 | 
			
		||||
 | 
			
		||||
    free(b->blobs);
 | 
			
		||||
    b->blobs = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_header(struct boot_img_hdr *hdr, const char *path)
 | 
			
		||||
{
 | 
			
		||||
    FILE *f = fopen(path, "r");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return -errno;
 | 
			
		||||
 | 
			
		||||
    int res = fread(hdr, sizeof(struct boot_img_hdr), 1, f);
 | 
			
		||||
    if(res == 1)
 | 
			
		||||
    {
 | 
			
		||||
        if(memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0)
 | 
			
		||||
            res = 0;
 | 
			
		||||
        else
 | 
			
		||||
            res = -EIO;
 | 
			
		||||
    }
 | 
			
		||||
    if(ferror(f))
 | 
			
		||||
        return LIBBOOTIMG_ERROR_IO;
 | 
			
		||||
    else if(feof(f))
 | 
			
		||||
        return LIBBOOTIMG_ERROR_IMG_EOF;
 | 
			
		||||
    else
 | 
			
		||||
        res = errno ? -errno : -EIO;
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dump_part(uint8_t *data, unsigned len, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    FILE *f;
 | 
			
		||||
 | 
			
		||||
    if(data == NULL)
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
 | 
			
		||||
    f = fopen(dest, "w");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return -errno;
 | 
			
		||||
 | 
			
		||||
    if(fwrite(data, len, 1, f) != 1)
 | 
			
		||||
        res = -errno;
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_kernel(struct bootimg *b, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    return dump_part(b->kernel, b->hdr.kernel_size, dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_ramdisk(struct bootimg *b, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    return dump_part(b->ramdisk, b->hdr.ramdisk_size, dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_second(struct bootimg *b, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    if(b->hdr.second_size == 0)
 | 
			
		||||
        return -ENOENT;
 | 
			
		||||
    return dump_part(b->second, b->hdr.second_size, dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_dtb(struct bootimg *b, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    if(b->hdr.dt_size == 0)
 | 
			
		||||
        return -ENOENT;
 | 
			
		||||
    return dump_part(b->dtb, b->hdr.dt_size, dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump(struct bootimg *b, const char *dest_dir)
 | 
			
		||||
{
 | 
			
		||||
    char dest[MAX_PATH_LEN];
 | 
			
		||||
    int res = 0;
 | 
			
		||||
 | 
			
		||||
    snprintf(dest, sizeof(dest), "%s/zImage", dest_dir);
 | 
			
		||||
    res = libbootimg_dump_kernel(b, dest);
 | 
			
		||||
 | 
			
		||||
    if(res == 0)
 | 
			
		||||
    {
 | 
			
		||||
        snprintf(dest, sizeof(dest), "%s/initrd.img", dest_dir);
 | 
			
		||||
        res = libbootimg_dump_ramdisk(b, dest);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(res == 0 && b->hdr.second_size)
 | 
			
		||||
    {
 | 
			
		||||
        snprintf(dest, sizeof(dest), "%s/second.img", dest_dir);
 | 
			
		||||
        res = libbootimg_dump_second(b, dest);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(res == 0 && b->hdr.dt_size)
 | 
			
		||||
    {
 | 
			
		||||
        snprintf(dest, sizeof(dest), "%s/dtb.img", dest_dir);
 | 
			
		||||
        res = libbootimg_dump_dtb(b, dest);
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int load_part(uint8_t **data, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    struct stat info;
 | 
			
		||||
    if(stat(src, &info) < 0)
 | 
			
		||||
        return -errno;
 | 
			
		||||
 | 
			
		||||
    if(info.st_size > INT_MAX)
 | 
			
		||||
        return -EFBIG;
 | 
			
		||||
 | 
			
		||||
    // probably /dev/null
 | 
			
		||||
    if(info.st_size == 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    FILE *f = fopen(src, "r");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return -errno;
 | 
			
		||||
 | 
			
		||||
    int res = info.st_size;
 | 
			
		||||
    *data = realloc(*data, info.st_size);
 | 
			
		||||
 | 
			
		||||
    if(fread(*data, info.st_size, 1, f) != 1)
 | 
			
		||||
    {
 | 
			
		||||
        res = -EIO;
 | 
			
		||||
        free(*data);
 | 
			
		||||
        *data = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_kernel(struct bootimg *b, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    int res = load_part(&b->kernel, src);
 | 
			
		||||
    if(res >= 0)
 | 
			
		||||
        b->hdr.kernel_size = res;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_ramdisk(struct bootimg *b, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    int res = load_part(&b->ramdisk, src);
 | 
			
		||||
    if(res >= 0)
 | 
			
		||||
        b->hdr.ramdisk_size = res;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_second(struct bootimg *b, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    int res = load_part(&b->second, src);
 | 
			
		||||
    if(res >= 0)
 | 
			
		||||
        b->hdr.second_size = res;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_dtb(struct bootimg *b, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    int res = load_part(&b->dtb, src);
 | 
			
		||||
    if(res >= 0)
 | 
			
		||||
        b->hdr.dt_size = res;
 | 
			
		||||
    return res;
 | 
			
		||||
        return LIBBOOTIMG_ERROR_OTHER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 32bit FNV-1a hash algorithm
 | 
			
		||||
// http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
 | 
			
		||||
static uint32_t calc_fnv_hash(void *data, unsigned len)
 | 
			
		||||
{
 | 
			
		||||
    static const uint32_t FNV_prime = 16777619U;
 | 
			
		||||
    static const uint32_t offset_basis = 2166136261U;
 | 
			
		||||
    const uint32_t FNV_prime = 16777619U;
 | 
			
		||||
    const uint32_t offset_basis = 2166136261U;
 | 
			
		||||
 | 
			
		||||
    uint32_t *d = (uint32_t*)data;
 | 
			
		||||
    uint32_t i, max;
 | 
			
		||||
@@ -311,30 +69,269 @@ static uint32_t calc_fnv_hash(void *data, unsigned len)
 | 
			
		||||
 | 
			
		||||
static void fill_id_hashes(struct bootimg *b)
 | 
			
		||||
{
 | 
			
		||||
    b->hdr.id[0] = calc_fnv_hash(b->kernel, b->hdr.kernel_size);
 | 
			
		||||
    b->hdr.id[1] = calc_fnv_hash(b->ramdisk, b->hdr.ramdisk_size);
 | 
			
		||||
    b->hdr.id[2] = calc_fnv_hash(b->second, b->hdr.second_size);
 | 
			
		||||
    int i = 0;
 | 
			
		||||
 | 
			
		||||
    b->hdr.id[3] = calc_fnv_hash(&b->hdr.kernel_addr, sizeof(b->hdr.kernel_addr));
 | 
			
		||||
    b->hdr.id[4] = calc_fnv_hash(&b->hdr.ramdisk_addr, sizeof(b->hdr.ramdisk_addr));
 | 
			
		||||
    b->hdr.id[5] = calc_fnv_hash(&b->hdr.second_addr, sizeof(b->hdr.second_addr));
 | 
			
		||||
    // hash blobs
 | 
			
		||||
    for(; i < LIBBOOTIMG_BLOB_CNT && i < 5; ++i)
 | 
			
		||||
        b->hdr.id[i] = calc_fnv_hash(b->blobs[i].data, *b->blobs[i].size);
 | 
			
		||||
 | 
			
		||||
    // hash kernel, ramdisk and second _addr and _size together
 | 
			
		||||
    b->hdr.id[i++] = calc_fnv_hash(&b->hdr.kernel_size, sizeof(uint32_t)*6);
 | 
			
		||||
 | 
			
		||||
    // hash tags_addr, page_size, dt_size and unused together
 | 
			
		||||
    b->hdr.id[6] = calc_fnv_hash(&b->hdr.tags_addr, sizeof(b->hdr.tags_addr)*4);
 | 
			
		||||
    b->hdr.id[i++] = calc_fnv_hash(&b->hdr.tags_addr, sizeof(uint32_t)*4);
 | 
			
		||||
 | 
			
		||||
    // cmdline is directly after name, so hash them together
 | 
			
		||||
    b->hdr.id[7] = calc_fnv_hash(b->hdr.name, BOOT_NAME_SIZE + strlen((char*)b->hdr.cmdline));
 | 
			
		||||
    b->hdr.id[i++] = calc_fnv_hash(b->hdr.name, BOOT_NAME_SIZE + strlen((char*)b->hdr.cmdline));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void libbootimg_init_new(struct bootimg *img)
 | 
			
		||||
{
 | 
			
		||||
    memset(img, 0, sizeof(struct bootimg));
 | 
			
		||||
    memcpy(img->hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
 | 
			
		||||
    img->hdr.page_size = DEFAULT_PAGE_SIZE;
 | 
			
		||||
 | 
			
		||||
    img->blobs[LIBBOOTIMG_BLOB_KERNEL].size = &img->hdr.kernel_size;
 | 
			
		||||
    img->blobs[LIBBOOTIMG_BLOB_RAMDISK].size = &img->hdr.ramdisk_size;
 | 
			
		||||
    img->blobs[LIBBOOTIMG_BLOB_SECOND].size = &img->hdr.second_size;
 | 
			
		||||
    img->blobs[LIBBOOTIMG_BLOB_DTB].size = &img->hdr.dt_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_init_load(struct bootimg *img, const char *path, int load_blob_mask)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    FILE *f;
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    int64_t addr;
 | 
			
		||||
    struct bootimg_blob *blob;
 | 
			
		||||
 | 
			
		||||
    libbootimg_init_new(img);
 | 
			
		||||
 | 
			
		||||
    res = libbootimg_load_header(&img->hdr, path);
 | 
			
		||||
    if(res < 0)
 | 
			
		||||
    {
 | 
			
		||||
        libbootimg_destroy(img);
 | 
			
		||||
        return res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    f = fopen(path, "r");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return translate_errnum(errno);
 | 
			
		||||
 | 
			
		||||
    addr = img->hdr.page_size;
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < LIBBOOTIMG_BLOB_CNT; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        blob = &img->blobs[i];
 | 
			
		||||
 | 
			
		||||
        if((load_blob_mask & (1 << i)) && *blob->size != 0)
 | 
			
		||||
        {
 | 
			
		||||
            if(fseek(f, addr, SEEK_SET) < 0)
 | 
			
		||||
            {
 | 
			
		||||
                if(errno == EINVAL)
 | 
			
		||||
                    res = LIBBOOTIMG_ERROR_IMG_EOF;
 | 
			
		||||
                else
 | 
			
		||||
                    res = translate_errnum(errno);
 | 
			
		||||
                goto fail;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            blob->data = malloc(*blob->size);
 | 
			
		||||
 | 
			
		||||
            if(fread(blob->data, *blob->size, 1, f) != 1)
 | 
			
		||||
            {
 | 
			
		||||
                res = translate_fread_error(f);
 | 
			
		||||
                goto fail;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        addr += align_size(*blob->size, img->hdr.page_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
    libbootimg_destroy(img);
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void libbootimg_destroy(struct bootimg *b)
 | 
			
		||||
{
 | 
			
		||||
    struct bootimg_blob *blob = b->blobs;
 | 
			
		||||
    struct bootimg_blob * const blobs_end = blob + LIBBOOTIMG_BLOB_CNT;
 | 
			
		||||
    for(; blob != blobs_end; ++blob)
 | 
			
		||||
    {
 | 
			
		||||
        free(blob->data);
 | 
			
		||||
        blob->data = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_header(struct boot_img_hdr *hdr, const char *path)
 | 
			
		||||
{
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    FILE *f = fopen(path, "r");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return translate_errnum(errno);
 | 
			
		||||
 | 
			
		||||
    if(fread(hdr, sizeof(struct boot_img_hdr), 1, f) == 1)
 | 
			
		||||
    {
 | 
			
		||||
        if(memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE) != 0)
 | 
			
		||||
            res = LIBBOOTIMG_ERROR_INVALID_MAGIC;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        res = translate_fread_error(f);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_blob(struct bootimg_blob *blob, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    FILE *f;
 | 
			
		||||
    int res = 0;
 | 
			
		||||
 | 
			
		||||
    if(blob->data == NULL)
 | 
			
		||||
        return LIBBOOTIMG_ERROR_NO_BLOB_DATA;
 | 
			
		||||
 | 
			
		||||
    f = fopen(dest, "w");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return translate_errnum(errno);
 | 
			
		||||
 | 
			
		||||
    if(fwrite(blob->data, *blob->size, 1, f) != 1)
 | 
			
		||||
        res = LIBBOOTIMG_ERROR_IO;
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_kernel(struct bootimg *b, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    return libbootimg_dump_blob(&b->blobs[LIBBOOTIMG_BLOB_KERNEL], dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_ramdisk(struct bootimg *b, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    return libbootimg_dump_blob(&b->blobs[LIBBOOTIMG_BLOB_RAMDISK], dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_second(struct bootimg *b, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    return libbootimg_dump_blob(&b->blobs[LIBBOOTIMG_BLOB_SECOND], dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_dump_dtb(struct bootimg *b, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    return libbootimg_dump_blob(&b->blobs[LIBBOOTIMG_BLOB_DTB], dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_blob(struct bootimg_blob *blob, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    FILE *f;
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    uint8_t *data;
 | 
			
		||||
    struct stat info;
 | 
			
		||||
 | 
			
		||||
    if(stat(src, &info) < 0)
 | 
			
		||||
        return translate_errnum(errno);
 | 
			
		||||
 | 
			
		||||
    if(info.st_size > INT_MAX)
 | 
			
		||||
        return LIBBOOTIMG_ERROR_FILE_TOO_BIG;
 | 
			
		||||
 | 
			
		||||
    // probably /dev/null
 | 
			
		||||
    if(info.st_size == 0)
 | 
			
		||||
    {
 | 
			
		||||
        free(blob->data);
 | 
			
		||||
        blob->data = NULL;
 | 
			
		||||
        *blob->size = 0;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    f = fopen(src, "r");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return translate_errnum(errno);
 | 
			
		||||
 | 
			
		||||
    data = malloc(info.st_size);
 | 
			
		||||
 | 
			
		||||
    if(fread(data, info.st_size, 1, f) == 1)
 | 
			
		||||
    {
 | 
			
		||||
        free(blob->data);
 | 
			
		||||
        blob->data = data;
 | 
			
		||||
        *blob->size = info.st_size;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        res = translate_fread_error(f);
 | 
			
		||||
        free(data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_kernel(struct bootimg *b, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    return libbootimg_load_blob(&b->blobs[LIBBOOTIMG_BLOB_KERNEL], src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_ramdisk(struct bootimg *b, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    return libbootimg_load_blob(&b->blobs[LIBBOOTIMG_BLOB_RAMDISK], src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_second(struct bootimg *b, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    return libbootimg_load_blob(&b->blobs[LIBBOOTIMG_BLOB_SECOND], src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_dtb(struct bootimg *b, const char *src)
 | 
			
		||||
{
 | 
			
		||||
    return libbootimg_load_blob(&b->blobs[LIBBOOTIMG_BLOB_DTB], src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_write_img(struct bootimg *b, const char *dest)
 | 
			
		||||
{
 | 
			
		||||
    if(b->hdr.kernel_size == 0 || b->hdr.ramdisk_size == 0 || b->hdr.page_size < sizeof(b->hdr))
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    FILE *f;
 | 
			
		||||
    int res;
 | 
			
		||||
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    FILE *f = fopen(dest, "w");
 | 
			
		||||
    if(b->hdr.kernel_size == 0 || b->hdr.ramdisk_size == 0)
 | 
			
		||||
        return LIBBOOTIMG_ERROR_MISSING_BLOB;
 | 
			
		||||
 | 
			
		||||
    if(b->hdr.page_size < sizeof(b->hdr))
 | 
			
		||||
        return LIBBOOTIMG_ERROR_INVALID_PAGESIZE;
 | 
			
		||||
 | 
			
		||||
    f = fopen(dest, "w");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return -errno;
 | 
			
		||||
        return translate_errnum(errno);
 | 
			
		||||
 | 
			
		||||
    res = libbootimg_write_img_fileptr(b, f);
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_write_img_fileptr(struct bootimg *b, FILE *f)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    char *blank = NULL;
 | 
			
		||||
    size_t padding;
 | 
			
		||||
    struct bootimg_blob *blob;
 | 
			
		||||
    int pos_start, pos_end;
 | 
			
		||||
 | 
			
		||||
    pos_start = ftell(f);
 | 
			
		||||
    if(pos_start < 0)
 | 
			
		||||
        return translate_errnum(errno);
 | 
			
		||||
 | 
			
		||||
    if(b->hdr.kernel_size == 0 || b->hdr.ramdisk_size == 0)
 | 
			
		||||
        return LIBBOOTIMG_ERROR_MISSING_BLOB;
 | 
			
		||||
 | 
			
		||||
    if(b->hdr.page_size < sizeof(b->hdr))
 | 
			
		||||
        return LIBBOOTIMG_ERROR_INVALID_PAGESIZE;
 | 
			
		||||
 | 
			
		||||
    // make sure it ends with 0
 | 
			
		||||
    b->hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;
 | 
			
		||||
@@ -345,54 +342,43 @@ int libbootimg_write_img(struct bootimg *b, const char *dest)
 | 
			
		||||
 | 
			
		||||
    fill_id_hashes(b);
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
    size_t to_write;
 | 
			
		||||
    char *blank = malloc(b->hdr.page_size);
 | 
			
		||||
    blank = malloc(b->hdr.page_size);
 | 
			
		||||
    memset(blank, 0, b->hdr.page_size);
 | 
			
		||||
 | 
			
		||||
    // write header
 | 
			
		||||
    if(fwrite(&b->hdr, sizeof(b->hdr), 1, f) != 1)
 | 
			
		||||
        goto fail;
 | 
			
		||||
        goto fail_fwrite;
 | 
			
		||||
 | 
			
		||||
    to_write = align_size(sizeof(b->hdr), b->hdr.page_size) - sizeof(b->hdr);
 | 
			
		||||
    if(fwrite(blank, sizeof(char), to_write, f) != to_write)
 | 
			
		||||
        goto fail;
 | 
			
		||||
 | 
			
		||||
    libbootimg_init_blob_table(b);
 | 
			
		||||
    padding = align_size(sizeof(b->hdr), b->hdr.page_size) - sizeof(b->hdr);
 | 
			
		||||
    if(fwrite(blank, 1, padding, f) != padding)
 | 
			
		||||
        goto fail_fwrite;
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < LIBBOOTIMG_BLOB_CNT; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        if(*b->blobs[i].size == 0)
 | 
			
		||||
        blob = &b->blobs[i];
 | 
			
		||||
 | 
			
		||||
        if(*blob->size == 0)
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        if(fwrite(*b->blobs[i].data, *b->blobs[i].size, 1, f) != 1)
 | 
			
		||||
            goto fail;
 | 
			
		||||
        if(fwrite(blob->data, *blob->size, 1, f) != 1)
 | 
			
		||||
            goto fail_fwrite;
 | 
			
		||||
 | 
			
		||||
        to_write = align_size(*b->blobs[i].size, b->hdr.page_size) - *b->blobs[i].size;
 | 
			
		||||
        if(fwrite(blank, sizeof(char), to_write, f) != to_write)
 | 
			
		||||
            goto fail;
 | 
			
		||||
        padding = align_size(*blob->size, b->hdr.page_size) - *blob->size;
 | 
			
		||||
        if(fwrite(blank, 1, padding, f) != padding)
 | 
			
		||||
            goto fail_fwrite;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // bootimg size (abootimg compatibility)
 | 
			
		||||
    if(b->size != 0)
 | 
			
		||||
    {
 | 
			
		||||
        if((int)b->size < ftell(f))
 | 
			
		||||
        {
 | 
			
		||||
            res = -EFBIG;
 | 
			
		||||
            remove(dest);
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
    pos_end = ftell(f);
 | 
			
		||||
 | 
			
		||||
        if(b->size_is_max_only == 0)
 | 
			
		||||
            ftruncate(fileno(f), b->size);
 | 
			
		||||
    }
 | 
			
		||||
    if(pos_end > 0)
 | 
			
		||||
        res = pos_end - pos_start;
 | 
			
		||||
    else
 | 
			
		||||
        res = translate_errnum(errno);
 | 
			
		||||
 | 
			
		||||
    goto exit;
 | 
			
		||||
fail:
 | 
			
		||||
    res = -errno;
 | 
			
		||||
    remove(dest);
 | 
			
		||||
fail_fwrite:
 | 
			
		||||
    res = LIBBOOTIMG_ERROR_IO;
 | 
			
		||||
exit:
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    free(blank);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
@@ -404,97 +390,6 @@ int libbootimg_write_img_and_destroy(struct bootimg *b, const char *dest)
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_config(struct bootimg *b, const char *src, int *error_line)
 | 
			
		||||
{
 | 
			
		||||
    FILE *f = fopen(src, "r");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return -errno;
 | 
			
		||||
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    int line_num = 0;
 | 
			
		||||
    char line[1024];
 | 
			
		||||
    while(fgets(line, sizeof(line), f))
 | 
			
		||||
    {
 | 
			
		||||
        if(libbootimg_load_config_line(b, line) < 0)
 | 
			
		||||
        {
 | 
			
		||||
            res = -1;
 | 
			
		||||
            if(error_line)
 | 
			
		||||
                *error_line = line_num;
 | 
			
		||||
            goto exit;
 | 
			
		||||
        }
 | 
			
		||||
        ++line_num;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_load_config_line(struct bootimg *b, char *line)
 | 
			
		||||
{
 | 
			
		||||
    char *s, *e;
 | 
			
		||||
    char *name_e;
 | 
			
		||||
    char *arg_s;
 | 
			
		||||
    size_t n_to_cmp;
 | 
			
		||||
 | 
			
		||||
    for(s = line; isspace(*s); ++s);
 | 
			
		||||
 | 
			
		||||
    for(e = s+strlen(s)-1; isspace(*e); --e)
 | 
			
		||||
        *e = 0;
 | 
			
		||||
 | 
			
		||||
    if(*s == 0 || (name_e = strchr(s, '=')) == NULL)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    arg_s = name_e+1;
 | 
			
		||||
 | 
			
		||||
    for(; isspace(*(name_e-1)) && name_e > s; --name_e);
 | 
			
		||||
    for(; isspace(*arg_s); ++arg_s);
 | 
			
		||||
 | 
			
		||||
    n_to_cmp = name_e-s;
 | 
			
		||||
 | 
			
		||||
    if(strncmp("bootsize", s, n_to_cmp) == 0)
 | 
			
		||||
        b->size = strtoll(arg_s, NULL, 16);
 | 
			
		||||
    else if(strncmp("pagesize", s, n_to_cmp) == 0)
 | 
			
		||||
        b->hdr.page_size = strtoll(arg_s, NULL, 16);
 | 
			
		||||
    else if(strncmp("kerneladdr", s, n_to_cmp) == 0)
 | 
			
		||||
        b->hdr.kernel_addr = strtoll(arg_s, NULL, 16);
 | 
			
		||||
    else if(strncmp("ramdiskaddr", s, n_to_cmp) == 0)
 | 
			
		||||
        b->hdr.ramdisk_addr = strtoll(arg_s, NULL, 16);
 | 
			
		||||
    else if(strncmp("secondaddr", s, n_to_cmp) == 0)
 | 
			
		||||
        b->hdr.second_addr = strtoll(arg_s, NULL, 16);
 | 
			
		||||
    else if(strncmp("tagsaddr", s, n_to_cmp) == 0)
 | 
			
		||||
        b->hdr.tags_addr = strtoll(arg_s, NULL, 16);
 | 
			
		||||
    else if(strncmp("name", s, n_to_cmp) == 0)
 | 
			
		||||
        strncpy((char*)b->hdr.name, arg_s, BOOT_NAME_SIZE);
 | 
			
		||||
    else if(strncmp("cmdline", s, n_to_cmp) == 0)
 | 
			
		||||
        strncpy((char*)b->hdr.cmdline, arg_s, BOOT_ARGS_SIZE);
 | 
			
		||||
    else
 | 
			
		||||
        return -1;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int libbootimg_write_config(struct bootimg *b, const char *dst)
 | 
			
		||||
{
 | 
			
		||||
    FILE *f = fopen(dst, "w");
 | 
			
		||||
    if(!f)
 | 
			
		||||
        return -errno;
 | 
			
		||||
 | 
			
		||||
    int res = fprintf(f,
 | 
			
		||||
        "bootsize = 0x%X\n"
 | 
			
		||||
        "pagesize = 0x%X\n"
 | 
			
		||||
        "kerneladdr = 0x%X\n"
 | 
			
		||||
        "ramdiskaddr = 0x%X\n"
 | 
			
		||||
        "secondaddr = 0x%X\n"
 | 
			
		||||
        "tagsaddr = 0x%X\n"
 | 
			
		||||
        "name = %s\n"
 | 
			
		||||
        "cmdline = %s\n",
 | 
			
		||||
        b->size, b->hdr.page_size, b->hdr.kernel_addr, b->hdr.ramdisk_addr,
 | 
			
		||||
        b->hdr.second_addr, b->hdr.tags_addr, b->hdr.name, b->hdr.cmdline);
 | 
			
		||||
 | 
			
		||||
    fclose(f);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t libbootimg_version(void)
 | 
			
		||||
{
 | 
			
		||||
    return LIBBOOTIMG_VERSION;
 | 
			
		||||
@@ -504,3 +399,23 @@ const char *libbootimg_version_str(void)
 | 
			
		||||
{
 | 
			
		||||
    return LIBBOOTIMG_VERSION_STR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *libbootimg_error_str(int error)
 | 
			
		||||
{
 | 
			
		||||
    switch(error)
 | 
			
		||||
    {
 | 
			
		||||
        case LIBBOOTIMG_SUCCESS:                return "No errors";
 | 
			
		||||
        case LIBBOOTIMG_ERROR_IO:               return "Input/output error";
 | 
			
		||||
        case LIBBOOTIMG_ERROR_ACCESS:           return "Permission denied";
 | 
			
		||||
        case LIBBOOTIMG_ERROR_NOT_FOUND:        return "No such file or directory";
 | 
			
		||||
        case LIBBOOTIMG_ERROR_INVALID_MAGIC:    return "Corrupted boot image, invalid magic";
 | 
			
		||||
        case LIBBOOTIMG_ERROR_IMG_EOF:          return "Corrupted boot image, premature end of file";
 | 
			
		||||
        case LIBBOOTIMG_ERROR_NO_BLOB_DATA:     return "No data loaded into this blob";
 | 
			
		||||
        case LIBBOOTIMG_ERROR_FILE_TOO_BIG:     return "File is too big";
 | 
			
		||||
        case LIBBOOTIMG_ERROR_MISSING_BLOB:     return "Missing required blob (kernel or ramdisk)";
 | 
			
		||||
        case LIBBOOTIMG_ERROR_INVALID_PAGESIZE: return "Invalid pagesize value";
 | 
			
		||||
 | 
			
		||||
        case LIBBOOTIMG_ERROR_OTHER:            return "Unhandled error";
 | 
			
		||||
        default:                                return "Unknown error";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user