linuxOS_D21X/source/artinchip/aic-logo/logo2part.c
2024-11-29 16:33:21 +08:00

360 lines
7.1 KiB
C

// SPDX-License-Identifier: Apache-2.0
/*
* Copyright (C) 2023 Artinchip Technology Co., Ltd.
* Authors: Huahui <huahui.mai@artinchip.com>
*/
#include <artinchip/sample_base.h>
#include <errno.h>
#include <mtd/mtd-user.h>
#include "image.h"
/* Global macro and variables */
#define MTD_DEV "/dev/mtd"
/* cmd-line flags */
#define FLAG_NONE 0x00
#define FLAG_LIST (0x1 << 1)
#define FLAG_SAVE (0x1 << 2)
#define FLAG_IMAGE (0x1 << 3)
#define DEV_TYPE_NONE 0
#define DEV_TYPE_BLK 1
#define DEV_TYPE_MTD 2
static const char sopts[] = "i:p:slu";
static const struct option lopts[] = {
{"input", required_argument, NULL, 'i'},
{"part", required_argument, NULL, 'p'},
{"list", no_argument, NULL, 'l'},
{"save", no_argument, NULL, 's'},
{"usage", no_argument, NULL, 'u'},
{0, 0, 0, 0}
};
struct file_object {
int fd;
unsigned int type;
unsigned int fsize;
unsigned char *buf;
struct mtd_info_user mtdinfo;
};
void usage(char *program)
{
printf("Usage: %s [options]: \n", program);
printf("\t -i, --input\t\tneed a file \n");
printf("\t -p, --part\t\tpart device \n");
printf("\t -l, --list\t\tlist logo part image \n");
printf("\t -s, --save\t\tsave logo.itb file \n");
printf("\t -u, --usage \n");
printf("\n");
printf("Example: %s -i boot_logo.png -p /dev/mtd7 \n", program);
}
static unsigned int part_type(const char *path)
{
unsigned int type = DEV_TYPE_NONE;
if (!strncmp(path, MTD_DEV, strlen(MTD_DEV)))
type = DEV_TYPE_MTD;
else if (strlen(path) > 0)
type = DEV_TYPE_BLK;
return type;
}
static int part_read(struct file_object *part)
{
unsigned char *buf;
int ret = 0;
buf = malloc(part->fsize);
if (!buf) {
ERR("malloc buf failed\n");
return -ENOMEM;
}
part->buf = buf;
ret = read(part->fd, buf, part->fsize);
if (ret != part->fsize) {
ERR("read part failed, ret(%d)\n", ret);
part->buf = NULL;
free(buf);
return -EIO;
}
return 0;
}
struct file_object *part_open(const char *path)
{
struct file_object *part;
int ret;
part = malloc(sizeof(struct file_object));
if (!part) {
ERR("malloc part object failed\n");
return NULL;
}
memset(part, 0, sizeof(*part));
part->type = part_type(path);
if (part->type == DEV_TYPE_NONE) {
ERR("device path is not correct\n");
goto out;
}
part->fd = open(path, O_RDWR);
if (part->fd < 0) {
ERR("Failed to open %s\n", path);
goto out;
}
if (part->type == DEV_TYPE_MTD) {
ret = ioctl(part->fd, MEMGETINFO, &part->mtdinfo);
if (ret < 0 || (part->mtdinfo.type != MTD_NORFLASH &&
part->mtdinfo.type != MTD_NANDFLASH)) {
ERR("ioctl MEMGETINFO failed\n");
goto out;
}
part->fsize = part->mtdinfo.size;
} else {
part->fsize = lseek(part->fd, 0, SEEK_END);
if (part->fsize < 0) {
ERR("get mmc part size failed\n");
goto out;
}
lseek(part->fd, 0, SEEK_SET);
}
ret = part_read(part);
if (ret)
goto out;
return part;
out:
if (part->fd > 0)
close(part->fd);
if (part)
free(part);
return NULL;
}
static void part_close(struct file_object *part)
{
if (!part)
return;
if (part->fd > 0)
close(part->fd);
if (part->buf)
free(part->buf);
}
struct file_object *image_open(const char *name)
{
struct file_object *image;
struct stat imagestat;
image = malloc(sizeof(struct file_object));
if (!image) {
ERR("malloc image object failed\n");
return NULL;
}
memset(image, 0x0, sizeof(*image));
image->fd = open(name, O_RDWR);
if (image->fd < 0) {
ERR("Failed to open %s. errno: %d[%s]\n",
name, errno, strerror(errno));
goto out;
}
if (fstat (image->fd, &imagestat) < 0) {
ERR("image get fstat failed\n");
goto out;
}
image->fsize = imagestat.st_size;
DBG("open(%s) %d, size %d\n",
name, image->fd, image->fsize);
image->buf = mmap(NULL, image->fsize,
PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
image->fd, 0);
if (image->buf == MAP_FAILED) {
ERR("mmap image failed, error: %d[%s]\n",
errno, strerror(errno));
goto out;
}
return image;
out:
if (image->fd > 0)
close(image->fd);
if (image)
free(image);
return NULL;
}
static void image_close(struct file_object *image)
{
if (!image)
return;
if (image->fd > 0)
close(image->fd);
if (image->buf)
munmap(image->buf, image->fsize);
}
static void itb_file_save(struct file_object *part)
{
FILE* fp_out;
fp_out= fopen("logo.itb", "wb");
fwrite(part->buf, 1, fdt_totalsize(part->buf), fp_out);
fclose(fp_out);
}
int fix_itb_file(struct file_object *part, struct file_object *image)
{
const char *name = "boot";
int noffset, ret;
size_t data_size;
const void *data;
int ovcopylen;
struct fdt_property *prop;
unsigned char *dst, *src;
unsigned char *end = part->buf + fdt_totalsize(part->buf);
/* Get specific logo image offset */
noffset = fit_image_get_node(part->buf, name);
if (noffset < 0) {
ERR("Failed to get %s node\n", name);
return noffset;
}
/* Load specific logo image */
ret = fit_image_get_data_and_size(part->buf, noffset, &data, &data_size);
if (ret < 0) {
ERR("Failed to get data\n");
return ret;
}
/* Update data size */
prop = fdt_get_property_w(part->buf, noffset, "data", NULL);
if (!prop) {
ERR("get data property failed\n");
return -FDT_ERR_INTERNAL;
}
prop->len = cpu_to_fdt32(image->fsize);
ovcopylen = FDT_TAGALIGN(image->fsize) - FDT_TAGALIGN(data_size);
if (ovcopylen > 0) {
src = (unsigned char *)data;
dst = (unsigned char *)data + ovcopylen;
} else {
src = (unsigned char *)data + FDT_TAGALIGN(data_size);
dst = src + ovcopylen;
}
memmove(dst, src, end - src);
memcpy((void *)data, image->buf, image->fsize);
fdt_set_totalsize(part->buf, fdt_totalsize(part->buf) + ovcopylen);
fdt_set_size_dt_struct(part->buf, fdt_size_dt_struct(part->buf) + ovcopylen);
fdt_set_off_dt_strings(part->buf, fdt_off_dt_strings(part->buf) + ovcopylen);
return 0;
}
int itb_to_part(struct file_object *part)
{
size_t size;
int ret;
if (part->type == DEV_TYPE_MTD) {
struct erase_info_user erase;
/* erase all */
erase.start = 0;
erase.length = part->mtdinfo.size;
if (ioctl(part->fd, MEMERASE, &erase) < 0) {
ERR("While erasing blocks 0x%.8x-0x%.8x on mtd7\n",
(unsigned int) erase.start,
(unsigned int) (erase.start + erase.length));
return -EIO;
}
}
size = fdt_totalsize(part->buf);
lseek(part->fd, 0, SEEK_SET);
ret = write(part->fd, part->buf, size);
if (ret != size) {
ERR("write new itb failed\n");
return -EIO;
}
return 0;
}
int main(int argc, char **argv)
{
int c = 0, flags = FLAG_NONE;
struct file_object *part = NULL;
struct file_object *image = NULL;
while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
switch (c) {
case 'i':
image = image_open(optarg);
if (image)
flags |= FLAG_IMAGE;
break;
case 'p':
part = part_open(optarg);
break;
case 'l':
flags |= FLAG_LIST;
break;
case 's':
flags |= FLAG_SAVE;
break;
case 'u':
usage(argv[0]);
return 0;
default:
usage(argv[0]);
return 0;
}
}
if (!part) {
ERR("device path is not correct\n");
goto out;
}
if (flags & FLAG_LIST)
fit_print_contents(part->buf);
if (flags & FLAG_IMAGE && !fix_itb_file(part, image))
itb_to_part(part);
if (flags & FLAG_SAVE)
itb_file_save(part);
out:
part_close(part);
image_close(image);
return 0;
}