uboot/cmd/bmp.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Detlev Zundel, DENX Software Engineering, dzu@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 * BMP handling routines
  10 */
  11
  12#include <common.h>
  13#include <dm.h>
  14#include <lcd.h>
  15#include <mapmem.h>
  16#include <bmp_layout.h>
  17#include <command.h>
  18#include <asm/byteorder.h>
  19#include <malloc.h>
  20#include <mapmem.h>
  21#include <splash.h>
  22#include <video.h>
  23
  24static int bmp_info (ulong addr);
  25
  26/*
  27 * Allocate and decompress a BMP image using gunzip().
  28 *
  29 * Returns a pointer to the decompressed image data. This pointer is
  30 * aligned to 32-bit-aligned-address + 2.
  31 * See doc/README.displaying-bmps for explanation.
  32 *
  33 * The allocation address is passed to 'alloc_addr' and must be freed
  34 * by the caller after use.
  35 *
  36 * Returns NULL if decompression failed, or if the decompressed data
  37 * didn't contain a valid BMP signature.
  38 */
  39#ifdef CONFIG_VIDEO_BMP_GZIP
  40struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
  41                             void **alloc_addr)
  42{
  43        void *dst;
  44        unsigned long len;
  45        struct bmp_image *bmp;
  46
  47        /*
  48         * Decompress bmp image
  49         */
  50        len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
  51        /* allocate extra 3 bytes for 32-bit-aligned-address + 2 alignment */
  52        dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE + 3);
  53        if (dst == NULL) {
  54                puts("Error: malloc in gunzip failed!\n");
  55                return NULL;
  56        }
  57
  58        bmp = dst;
  59
  60        /* align to 32-bit-aligned-address + 2 */
  61        bmp = (struct bmp_image *)((((unsigned int)dst + 1) & ~3) + 2);
  62
  63        if (gunzip(bmp, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, map_sysmem(addr, 0),
  64                   &len) != 0) {
  65                free(dst);
  66                return NULL;
  67        }
  68        if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)
  69                puts("Image could be truncated"
  70                                " (increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
  71
  72        /*
  73         * Check for bmp mark 'BM'
  74         */
  75        if (!((bmp->header.signature[0] == 'B') &&
  76              (bmp->header.signature[1] == 'M'))) {
  77                free(dst);
  78                return NULL;
  79        }
  80
  81        debug("Gzipped BMP image detected!\n");
  82
  83        *alloc_addr = dst;
  84        return bmp;
  85}
  86#else
  87struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
  88                             void **alloc_addr)
  89{
  90        return NULL;
  91}
  92#endif
  93
  94static int do_bmp_info(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
  95{
  96        ulong addr;
  97
  98        switch (argc) {
  99        case 1:         /* use load_addr as default address */
 100                addr = load_addr;
 101                break;
 102        case 2:         /* use argument */
 103                addr = simple_strtoul(argv[1], NULL, 16);
 104                break;
 105        default:
 106                return CMD_RET_USAGE;
 107        }
 108
 109        return (bmp_info(addr));
 110}
 111
 112static int do_bmp_display(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 113{
 114        ulong addr;
 115        int x = 0, y = 0;
 116
 117        splash_get_pos(&x, &y);
 118
 119        switch (argc) {
 120        case 1:         /* use load_addr as default address */
 121                addr = load_addr;
 122                break;
 123        case 2:         /* use argument */
 124                addr = simple_strtoul(argv[1], NULL, 16);
 125                break;
 126        case 4:
 127                addr = simple_strtoul(argv[1], NULL, 16);
 128                x = simple_strtoul(argv[2], NULL, 10);
 129                y = simple_strtoul(argv[3], NULL, 10);
 130                break;
 131        default:
 132                return CMD_RET_USAGE;
 133        }
 134
 135         return (bmp_display(addr, x, y));
 136}
 137
 138static cmd_tbl_t cmd_bmp_sub[] = {
 139        U_BOOT_CMD_MKENT(info, 3, 0, do_bmp_info, "", ""),
 140        U_BOOT_CMD_MKENT(display, 5, 0, do_bmp_display, "", ""),
 141};
 142
 143#ifdef CONFIG_NEEDS_MANUAL_RELOC
 144void bmp_reloc(void) {
 145        fixup_cmdtable(cmd_bmp_sub, ARRAY_SIZE(cmd_bmp_sub));
 146}
 147#endif
 148
 149/*
 150 * Subroutine:  do_bmp
 151 *
 152 * Description: Handler for 'bmp' command..
 153 *
 154 * Inputs:      argv[1] contains the subcommand
 155 *
 156 * Return:      None
 157 *
 158 */
 159static int do_bmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 160{
 161        cmd_tbl_t *c;
 162
 163        /* Strip off leading 'bmp' command argument */
 164        argc--;
 165        argv++;
 166
 167        c = find_cmd_tbl(argv[0], &cmd_bmp_sub[0], ARRAY_SIZE(cmd_bmp_sub));
 168
 169        if (c)
 170                return  c->cmd(cmdtp, flag, argc, argv);
 171        else
 172                return CMD_RET_USAGE;
 173}
 174
 175U_BOOT_CMD(
 176        bmp,    5,      1,      do_bmp,
 177        "manipulate BMP image data",
 178        "info <imageAddr>          - display image info\n"
 179        "bmp display <imageAddr> [x y] - display image at x,y"
 180);
 181
 182/*
 183 * Subroutine:  bmp_info
 184 *
 185 * Description: Show information about bmp file in memory
 186 *
 187 * Inputs:      addr            address of the bmp file
 188 *
 189 * Return:      None
 190 *
 191 */
 192static int bmp_info(ulong addr)
 193{
 194        struct bmp_image *bmp = (struct bmp_image *)map_sysmem(addr, 0);
 195        void *bmp_alloc_addr = NULL;
 196        unsigned long len;
 197
 198        if (!((bmp->header.signature[0]=='B') &&
 199              (bmp->header.signature[1]=='M')))
 200                bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr);
 201
 202        if (bmp == NULL) {
 203                printf("There is no valid bmp file at the given address\n");
 204                return 1;
 205        }
 206
 207        printf("Image size    : %d x %d\n", le32_to_cpu(bmp->header.width),
 208               le32_to_cpu(bmp->header.height));
 209        printf("Bits per pixel: %d\n", le16_to_cpu(bmp->header.bit_count));
 210        printf("Compression   : %d\n", le32_to_cpu(bmp->header.compression));
 211
 212        if (bmp_alloc_addr)
 213                free(bmp_alloc_addr);
 214
 215        return(0);
 216}
 217
 218/*
 219 * Subroutine:  bmp_display
 220 *
 221 * Description: Display bmp file located in memory
 222 *
 223 * Inputs:      addr            address of the bmp file
 224 *
 225 * Return:      None
 226 *
 227 */
 228int bmp_display(ulong addr, int x, int y)
 229{
 230#ifdef CONFIG_DM_VIDEO
 231        struct udevice *dev;
 232#endif
 233        int ret;
 234        struct bmp_image *bmp = map_sysmem(addr, 0);
 235        void *bmp_alloc_addr = NULL;
 236        unsigned long len;
 237
 238        if (!((bmp->header.signature[0]=='B') &&
 239              (bmp->header.signature[1]=='M')))
 240                bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr);
 241
 242        if (!bmp) {
 243                printf("There is no valid bmp file at the given address\n");
 244                return 1;
 245        }
 246        addr = map_to_sysmem(bmp);
 247
 248#ifdef CONFIG_DM_VIDEO
 249        ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
 250        if (!ret) {
 251                bool align = false;
 252
 253# ifdef CONFIG_SPLASH_SCREEN_ALIGN
 254                align = true;
 255# endif /* CONFIG_SPLASH_SCREEN_ALIGN */
 256                ret = video_bmp_display(dev, addr, x, y, align);
 257        }
 258#elif defined(CONFIG_LCD)
 259        ret = lcd_display_bitmap(addr, x, y);
 260#elif defined(CONFIG_VIDEO)
 261        ret = video_display_bitmap(addr, x, y);
 262#else
 263# error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO
 264#endif
 265
 266        if (bmp_alloc_addr)
 267                free(bmp_alloc_addr);
 268
 269        return ret ? CMD_RET_FAILURE : 0;
 270}
 271