// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2008 Freescale Semiconductor, Inc.
* Copyright 2013 Wolfgang Denk <wd@denx.de>
*/
/*
* This file provides a shell like 'expr' function to return.
*/
#include <common.h>
#include <config.h>
#include <command.h>
#include <env.h>
#include <log.h>
#include <malloc.h>
#include <mapmem.h>
#include <linux/sizes.h>
/**
* struct expr_arg: Holds an argument to an expression
*
* @ival: Integer value (if width is not CMD_DATA_SIZE_STR)
* @sval: String value (if width is CMD_DATA_SIZE_STR)
*/
struct expr_arg {
union {
ulong ival;
char *sval;
};
};
static int get_arg(char *s, int w, struct expr_arg *argp)
{
struct expr_arg arg;
/*
* If the parameter starts with a '*' then assume it is a pointer to
* the value we want.
*/
if (s[0] == '*') {
ulong *p;
ulong addr;
ulong val;
int len;
char *str;
addr = simple_strtoul(&s[1], NULL, 16);
switch (w) {
case 1:
p = map_sysmem(addr, sizeof(uchar));
val = (ulong)*(uchar *)p;
unmap_sysmem(p);
arg.ival = val;
break;
case 2:
p = map_sysmem(addr, sizeof(ushort));
val = (ulong)*(ushort *)p;
unmap_sysmem(p);
arg.ival = val;
break;
case CMD_DATA_SIZE_STR:
p = map_sysmem(addr, SZ_64K);
/* Maximum string length of 64KB plus terminator */
len = strnlen((char *)p, SZ_64K) + 1;
str = malloc(len);
if (!str) {
printf("Out of memory\n");
return -ENOMEM;
}
memcpy(str, p, len);
str[len - 1] = '\0';
unmap_sysmem(p);
arg.sval = str;
break;
case 4:
p = map_sysmem(addr, sizeof(u32));
val = *(u32 *)p;
unmap_sysmem(p);
arg.ival = val;
break;
default:
p = map_sysmem(addr, sizeof(ulong));
val = *p;
unmap_sysmem(p);
arg.ival = val;
break;
}
} else {
if (w == CMD_DATA_SIZE_STR)
return -EINVAL;
arg.ival = simple_strtoul(s, NULL, 16);
}
*argp = arg;
return 0;
}
#ifdef CONFIG_REGEX
|