Files
bs_explorer/src/modules/script/env.c
François d1bdce91dc restructure: code+libs under src/, runtime resources under data/
Separate the two concerns the repo root was mixing:
- src/   — bs/, modules/, libs/ (code + vendored libs)
- data/  — fpga_registry.yaml, probes.yaml, bsdl_files/, bscan_proxies/,
           scripts/ (everything the tool reads at runtime, CWD-relative)
- doc/   — kept at the root

CMake: repoint DIR_MODULES/DIR_LIBS and add_subdirectory at src/; emit
the binary at the build/ root (build/bs) via CMAKE_RUNTIME_OUTPUT_DIRECTORY
instead of the nested build/src/bs/. The jtag_core ../../libs path still
resolves since modules and libs moved together.

Runtime default paths now point under data/ (fpga.c, probes.c, script.c
bsdl_files lookup, init.c config.script). Docs (README/tutorial/CLAUDE)
updated for the new layout, src/ module paths, and ./build/bs.

Validated on the IGLOO2/FlashPro: profiles, autoinit, and svf_play all
work run from the repo root.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 15:03:25 +02:00

592 lines
11 KiB
C

/*
* JTAG Boundary Scanner
* Copyright (c) 2008 - 2024 Viveris Technologies
*
* JTAG Boundary Scanner is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* JTAG Boundary Scanner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 3 for more details.
*
* You should have received a copy of the GNU General Public License
* along with JTAG Boundary Scanners; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file env.c
* @brief Internal variables support.
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include "config/bs_defines.h"
#include "env.h"
/*
|L|H|str varname\0|L|H|str vardata\0|L|H|str varname\0|L|H|str vardata\0|0|0|
(H*256)+L = str size (\0 included)
if L & H == 0 -> end of buffer
*/
static int stringcopy(char * dst, char * src, unsigned int maxsize)
{
int s;
if( !dst || (maxsize <= 0))
return 0;
if( !src )
{
*dst = '\0';
return 1;
}
s = 0;
while( *src && s < (maxsize - 1))
{
*dst++ = *src++;
s++;
}
*dst = '\0';
s++;
return s;
}
static uint16_t getEnvStrSize(unsigned char * buf)
{
uint16_t size;
size = *buf++;
size += (((uint16_t)*buf)<<8);
return size;
}
static void setEnvStrSize(unsigned char * buf, uint16_t size)
{
*buf++ = size & 0xFF;
*buf = (size >> 8) & 0xFF;
return;
}
static int getEnvEmptyOffset(envvar_entry * env)
{
int off;
unsigned short varname_size, vardata_size;
off = 0;
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
while( varname_size )
{
off += (2 + varname_size + 2 + vardata_size);
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
}
return off;
}
static int getEnvBufOff(envvar_entry * env, char * varname)
{
unsigned short curstr_size;
int str_index,i;
i = 0;
str_index = 0;
curstr_size = getEnvStrSize(&env->buf[i]);
i += 2;
while( curstr_size )
{
if( !(str_index & 1) ) // variable name ?
{
if( !strcmp((char*)&env->buf[i],varname ) )
{
// this is the variable we are looking for.
return (i - 2);
}
else
{
// not the right variable - skip this string.
i += curstr_size;
}
}
else
{
//variable data - skip this string.
i += curstr_size;
}
if( i < env->bufsize - 2 )
{
curstr_size = getEnvStrSize(&env->buf[i]);
i += 2;
}
else
{
curstr_size = 0;
}
str_index++;
}
return -1; // Not found.
}
static int pushStr(envvar_entry * env, int offset, char * str)
{
int size;
if(!str || offset < 0)
return -1;
size = strlen(str) + 1;
if(size > 0xFFFF)
return -1;
if( ( offset + 2 + size ) < env->bufsize )
{
setEnvStrSize(&env->buf[offset], size);
offset += 2;
stringcopy((char*)&env->buf[offset], str, size);
offset += size;
return offset;
}
return -1;
}
#ifndef STATIC_ENV_BUFFER
static envvar_entry * realloc_env_buffer(envvar_entry * env, unsigned int size)
{
unsigned int tmp_bufsize;
unsigned char * tmpbuf;
if( !env )
{
env = malloc( sizeof(envvar_entry) );
if(!env)
return NULL;
memset( env,0,sizeof(envvar_entry));
}
tmp_bufsize = size;
if( tmp_bufsize & (ENV_PAGE_SIZE - 1) )
{
tmp_bufsize = (tmp_bufsize & (~(ENV_PAGE_SIZE - 1))) + ENV_PAGE_SIZE;
}
if( tmp_bufsize > ENV_MAX_TOTAL_BUFFER_SIZE )
{
return env;
}
if( env->bufsize != tmp_bufsize )
{
tmpbuf = realloc(env->buf, tmp_bufsize);
if(tmpbuf)
{
if( env->bufsize < tmp_bufsize )
memset(&tmpbuf[env->bufsize], 0, tmp_bufsize - env->bufsize );
env->bufsize = tmp_bufsize;
env->buf = tmpbuf;
}
}
return env;
}
#endif
static int pushEnvEntry(envvar_entry * env, char * varname, char * vardata)
{
unsigned int total_size;
int varname_len,vardata_len;
int offset;
if(!varname || !vardata)
return -1;
varname_len = strlen(varname) + 1;
vardata_len = strlen(vardata) + 1;
if( varname_len > ENV_MAX_STRING_SIZE || vardata_len > ENV_MAX_STRING_SIZE)
{
return -2;
}
total_size = 2 + varname_len + 2 + vardata_len;
offset = getEnvEmptyOffset(env);
if( offset < 0 )
{
return -1;
}
#ifndef STATIC_ENV_BUFFER
realloc_env_buffer(env, offset + total_size + 4);
#endif
if( (total_size + offset) < env->bufsize )
{
offset = pushStr(env, offset, varname);
offset = pushStr(env, offset, vardata);
return offset;
}
return -1;
}
int setEnvVarDat( envvar_entry * env, char * varname, char * vardata )
{
int i,off,ret;
unsigned short varname_size, vardata_size;
int varname_len, vardata_len;
int oldentrysize;
ret = 0;
if(!env)
return -1;
i = 0;
varname_len = 0;
vardata_len = 0;
if( !varname )
return -1;
varname_len = strlen(varname);
if( vardata )
vardata_len = strlen(vardata);
if( varname_len > ENV_MAX_STRING_SIZE || vardata_len > ENV_MAX_STRING_SIZE)
{
return -1;
}
off = getEnvBufOff( env, varname );
if( off >= 0 )
{
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
oldentrysize = 2 + varname_size + 2 + vardata_size;
if(vardata)
{
vardata_len = strlen(vardata);
if( vardata_len + 1 > 0xFFFF )
return -1;
if( vardata_len + 1 > vardata_size )
{
// add new entry, and pack the strings
ret = pushEnvEntry(env, varname, vardata);
if( ret > 0 )
{
unsigned char byte;
for(i=0;i<env->bufsize - (off + oldentrysize);i++)
{
byte = env->buf[off + i + oldentrysize];
env->buf[off + i + oldentrysize] = '\0';
env->buf[off + i] = byte;
}
}
}
else
{
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
if(vardata_size)
{
memset((char*)&env->buf[off + 2 + varname_size + 2], 0, vardata_size );
stringcopy( (char*)&env->buf[off + 2 + varname_size + 2], vardata, vardata_size);
}
}
}
else
{
// unset variable
unsigned char byte;
for(i=0;i<env->bufsize - (off + oldentrysize);i++)
{
byte = env->buf[off + i + oldentrysize];
env->buf[off + i + oldentrysize] = '\0';
env->buf[off + i] = byte;
}
}
}
else
{
if(vardata)
{
// New variable
ret = pushEnvEntry(env, varname, vardata);
}
}
return ret;
}
char * getEnvVarDat( envvar_entry * env, char * varname, char * vardata, int maxsize)
{
int off;
unsigned short varname_size, vardata_size;
envvar_entry * tmp_envvars;
tmp_envvars = (envvar_entry *)env;
if(!tmp_envvars)
return NULL;
off = getEnvBufOff( env, varname );
if( off >= 0 )
{
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
if( varname_size>0 && vardata_size>0)
{
if(vardata)
{
stringcopy(vardata, (char*)&env->buf[off + 2 + varname_size + 2], maxsize);
}
return (char*)&env->buf[off + 2 + varname_size + 2];
}
}
return NULL;
}
env_var_value getEnvVarValue( envvar_entry * env, char * varname)
{
env_var_value value;
char * str_return;
value = 0;
if(!varname)
return 0;
str_return = getEnvVarDat( env, varname, NULL, 0);
if(str_return)
{
if( strlen(str_return) > 2 )
{
if( str_return[0]=='0' && ( str_return[1]=='x' || str_return[1]=='X'))
{
value = (env_var_value)STRTOVALUE(str_return, NULL, 0);
}
else
{
value = atoi(str_return);
}
}
else
{
value = atoi(str_return);
}
}
return value;
}
int setEnvVarValue( envvar_entry * env, char * varname, env_var_value value)
{
char tmp_str[128];
tmp_str[128 - 1] = 0;
snprintf(tmp_str,sizeof(tmp_str) - 1, "%d",value);
return setEnvVarDat( env, varname, tmp_str );
}
char * getEnvVarDatIndex( envvar_entry * env, int index, char * vardata, int maxsize)
{
int str_index, off;
unsigned short varname_size, vardata_size;
off = 0;
str_index = 0;
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
while( varname_size )
{
if( str_index == index )
{
if( varname_size>0 && vardata_size>0)
{
if(vardata)
{
stringcopy(vardata,(char*)&env->buf[off + 2 + varname_size + 2], maxsize);
}
return (char*)&env->buf[off + 2];
}
}
off += (2 + varname_size + 2 + vardata_size);
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
str_index++;
}
return NULL; // Not found.
}
envvar_entry * initEnv(envvar_entry * src, envvar_entry * dst)
{
if( !dst )
{
#ifdef STATIC_ENV_BUFFER
return NULL;
#else
dst = malloc( sizeof(envvar_entry) );
if(!dst)
return NULL;
memset( dst, 0, sizeof(envvar_entry) );
if( src )
dst->bufsize = src->bufsize;
else
dst->bufsize = ENV_PAGE_SIZE;
dst->buf = malloc(dst->bufsize);
if(!dst->buf)
{
free(dst);
return NULL;
}
if( src )
memcpy( dst->buf, src->buf, src->bufsize );
else
memset( dst->buf, 0, dst->bufsize );
return dst;
#endif
}
else
{
#ifdef STATIC_ENV_BUFFER
memset( dst, 0, sizeof(envvar_entry) );
dst->bufsize = ENV_PAGE_SIZE;
if(src)
{
memcpy( dst->buf, src->buf, dst->bufsize );
}
else
{
memset( dst->buf, 0, dst->bufsize );
}
return dst;
#else
free(dst->buf);
dst->buf = NULL;
if( src )
dst->bufsize = src->bufsize;
else
dst->bufsize = ENV_PAGE_SIZE;
dst->buf = malloc(dst->bufsize);
if(!dst->buf)
{
dst->bufsize = 0;
return NULL;
}
if(src)
{
memcpy( dst->buf, src->buf, dst->bufsize );
}
else
{
memset( dst->buf, 0, dst->bufsize );
}
return dst;
#endif
}
return NULL;
}
int jtagcore_setEnvVar( jtag_core * jc, char * varname, char * varvalue )
{
if( setEnvVarDat( jc->envvar, varname, varvalue ) >= 0 )
{
return JTAG_CORE_NO_ERROR;
}
else
{
return JTAG_CORE_MEM_ERROR;
}
}
char * jtagcore_getEnvVar( jtag_core * jc, char * varname, char * varvalue)
{
return getEnvVarDat( jc->envvar, varname, varvalue, 512 );
}
char * jtagcore_getEnvVarIndex( jtag_core * jc, int index, char * varvalue)
{
return getEnvVarDatIndex( jc->envvar, index, varvalue, 512 );
}
int jtagcore_getEnvVarValue( jtag_core * jc, char * varname)
{
return getEnvVarValue( jc->envvar, varname);
}
void deinitEnv(envvar_entry * env)
{
#ifndef STATIC_ENV_BUFFER
if(!env)
return;
free(env->buf);
free(env);
#else
memset(env,0,sizeof(envvar_entry));
#endif
return;
}