9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 72132b63edb25a63073636e379749ee395666ed5
parent 22433ef0cf2fddc3e88733e6bb1e1d4693f7aa92
Author: Joel Hutton <Joel.Hutton@Arm.com>
Date:   Fri, 26 Oct 2018 17:42:56 +0100

Add hosted language interface

A program to manipulate the trapframe, do RMC calls and inspect the
result.
commands are:

read [register name] [optional base 10 or 16, default 10]
Returns the register, in the base format specified.

set [register name] [value] [optional base >1, base<16, default 10]
Sets the register to value in the base specified. Implicit hex in format
0x... is supported.

dump
Prints out all the register values

trap
Calls trap(&tf)

rmc [rmc command name]
rmc [class] [func]
Populates the esr with RMC error cause, class value and func value then
calls trap.

Change-Id: I45b89ac168bb17f3ed85a52e7025a0b12423ba2f
Signed-off-by: Joel Hutton <Joel.Hutton@Arm.com>

Diffstat:
Aarch/amd64/hosted.c | 324+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ascripts/genhosted.sh | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 423 insertions(+), 0 deletions(-)

diff --git a/arch/amd64/hosted.c b/arch/amd64/hosted.c @@ -0,0 +1,324 @@ +#include <errno.h> +#include <rcode.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <hosted.h> + +void +print_tf(struct trapframe *tfp) +{ + printf("x0=0x%llx\tx1=0x%llx\tx2=0x%llx\tx3=0x%llx\n" + "x4=0x%llx\tx5=0x%llx\tx6=0x%llx\tx7=0x%llx\n" + "x8=0x%llx\tx9=0x%llx\tx10=0x%llx\tx11=0x%llx\n" + "x12=0x%llx\tx13=0x%llx\tx14=0x%llx\tx15=0x%llx\n" + "x16=0x%llx\tx17=0x%llx\tx18=0x%llx\tx19=0x%llx\n" + "x20=0x%llx\tx21=0x%llx\tx22=0x%llx\tx23=0x%llx\n" + "x24=0x%llx\tx25=0x%llx\tx26=0x%llx\tx27=0x%llx\n" + "x28=0x%llx\tx29=0x%llx\tx30=0x%llx\telr=%p\n" + "spsr=0x%llx\tesr=0x%llx\tfar=0x%llx\n" + "sp=0x%p\n", + tfp->x0, tfp->x1, tfp->x2, tfp->x3, + tfp->x4, tfp->x5, tfp->x6, tfp->x7, + tfp->x8, tfp->x9, tfp->x10, tfp->x11, + tfp->x12, tfp->x13, tfp->x14, tfp->x15, + tfp->x16, tfp->x17, tfp->x18, tfp->x19, + tfp->x20, tfp->x21, tfp->x22, tfp->x23, + tfp->x24, tfp->x25, tfp->x26, tfp->x27, + tfp->x28, tfp->x29, tfp->x30, tfp->elr, + tfp->spsr, tfp->esr, tfp->far, tfp->sp); +} + +/* Read a value in a given base between 2 and 16 0 means default base; + * 10, unless the string begins with "0x" or "0b" + */ +unsigned long long +base_read(char* str, int base, int *err) +{ + unsigned long long val; + char *endptr; + + endptr = NULL; + errno = 0; + val = strtoull(str, &endptr, base); + if (str == endptr || errno != 0){ + ERROR("strtoull error with '%s' in base %d\n", str, base); + if(err != NULL) + *err = 1; + } + return val; +} + +/* Get reg struct for named reg */ +unsigned long long* +get_named_reg(char* name, struct trapframe* tfp) +{ + size_t i; + char *regptr; + + regptr=NULL; + for(i=0;i<NUM_NAMED_REGS;i++){ + if(strcmp(name,named_regs[i].name)==0){ + regptr = (char*) tfp; + regptr += named_regs[i].offset; + } + } + return (unsigned long long*) regptr; +} + +/* Get rmc_command struct for named rmc command */ +const struct rmc_command* +get_rmc_cmd(char* name) +{ + size_t i; + + for(i=0;i<NUM_RMC_COMMANDS;i++){ + if(strcmp(name,rmc_commands[i].name)==0){ + return &rmc_commands[i]; + } + } + return NULL; +} + +/* Get command struct for named command */ +const struct command* +get_command(char* name) +{ + size_t i; + + for(i=0;i<NUM_COMMANDS;i++){ + if(strcmp(name,commands[i].name)==0){ + return &commands[i]; + } + } + return NULL; +} + +int +do_set(char** argv,int argc, struct trapframe* tfp) +{ + unsigned long long *reg=NULL; + unsigned long long setval=0; + unsigned int base; + int err; + + err = 0; + + reg = get_named_reg(argv[1],tfp); + if( reg == NULL){ + ERROR("Register '%s' not found\n",argv[1]); + return 1; + } + + base = 0; + + switch(argc){ + case 4: + base = base_read(argv[3], 10, &err); + if(err) + return 1; + /* fallthrough */ + case 3: + setval = base_read(argv[2], base, &err); + if(err) + return 1; + break; + default: + ERROR("Invalid number of parameters for set\n"); + return 1; + } + INFO("set:0x%llx\n",setval); + *reg=setval; + return 0; +} + +int +do_read(char** argv,int argc, struct trapframe* tfp) +{ + unsigned long long* reg=NULL; + char* format_string; + + reg = get_named_reg(argv[1],tfp); + if(reg == NULL){ + ERROR("Register '%s' not found\n",argv[1]); + return 1; + } + + switch(argc){ + case 3: + switch(atoi(argv[2])){ + case 10: + format_string="%llu\n"; + break; + case 16: + format_string="%llx\n"; + break; + default: + ERROR("Unsupported base for read:%s\nsupported: 10,16\n", + argv[2]); + return 1; + } + break; + case 2: + format_string="%llu\n"; + break; + default: + ERROR("Invalid number of arguments for read\n"); + return 1; + } + printf(format_string,*reg); + return 0; +} + +int +do_dump(char** argv,int argc, struct trapframe* tfp) +{ + print_tf(tfp); + return 0; +} + +int +do_trap(char** argv,int argc, struct trapframe* tfp) +{ + trap(tfp); + return 0; +} + +int +do_rmc(char** argv,int argc, struct trapframe* tfp) +{ + unsigned char class; + unsigned char func; + unsigned int base; + const struct rmc_command *rmc_cmd; + int err; + + err = 0; + + base = 0; + switch(argc){ + case 4: + base = base_read(argv[3], 10, &err); + if(err) + return 1; + /* fallthrough */ + case 3: + class = base_read(argv[1], base, &err); + func = base_read(argv[2], base, &err); + if(err) + return 1; + break; + case 2: + rmc_cmd = get_rmc_cmd(argv[1]); + if (rmc_cmd == NULL){ + ERROR("rmc '%s' not found\n",argv[1]); + return 1; + } + class = rmc_cmd->class; + func = rmc_cmd->func; + break; + default: + ERROR("Invalid number of parameters for rmc\n"); + return 1; + } + INFO("class:%d,func:%d\n",class,func); + tfp->esr=(unsigned long long) RMC<<26; + tfp->esr |= class; + tfp->esr |= (func<<8); + trap(tfp); + return 0; +} + +/* Separate buffer whitespace */ +void +tokenise(char* buff, char** argv, unsigned int* argc, char* sep) +{ + char* token; + + *argc=0; + token=strtok(buff,sep); + while(token!=NULL){ + argv[*argc]=token; + (*argc)++; + token=strtok(NULL,sep); + } + return; +} + +char* +trim(char* buff) +{ + int bufflen,i; + char* newbuff; + + newbuff = buff; + bufflen=strlen(buff); + + /* Trailing whitespace */ + for(i = bufflen-1; i>0; i--){ + if(buff[i]==' ' || buff[i]=='\t' || buff[i] == '\n'){ + buff[i]='\0';; + } + else{ + break; + } + } + /* Leading whitespace */ + for(i = 0; i<bufflen; i++){ + if(buff[i]==' ' || buff[i]=='\t' || buff[i] == '\n'){ + newbuff+=1; + } + else{ + break; + } + } + return newbuff; +} + +int +parse_cmd(char * cmd, struct trapframe* tfp) +{ + char* argv[MAX_PARTS]; + unsigned int argc; + const struct command* com; + + cmd = trim(cmd); + + /* Get array of strings by separating on whitespace */ + tokenise(cmd,argv,&argc," "); + + if(argc != 0){ + com = get_command(argv[0]); + } + + if(com == NULL){ + ERROR("Command '%s' not found\n",argv[0]); + return 1; + } + + /* Call eval function for specific command */ + com->eval(argv,argc, tfp); + return 0; +} + +int +main(int argc, char *argv[]) +{ + char buffer[BUFFER_SIZE]; + struct trapframe tf; + char* end; + + memset(&tf, 0, sizeof(struct trapframe)); + end=0; + do{ + printf("$ "); + fflush(stdout); + end = fgets(buffer,BUFFER_SIZE,stdin); + if(strlen(buffer)>1){ + parse_cmd(buffer,&tf); + } + fflush(stdout); + } + while(end != NULL); + return 0; +} diff --git a/scripts/genhosted.sh b/scripts/genhosted.sh @@ -0,0 +1,99 @@ +#!/bin/sh + +echo " +#define BUFFER_SIZE 256 +#define MAX_PARTS 50 + +#define DEBUG(...) do{fprintf(stderr,\"DEBUG:\"); fprintf(stderr,__VA_ARGS__);}while(0) +#define INFO(...) do{fprintf(stderr,\"INFO:\"); fprintf(stderr,__VA_ARGS__);}while(0) +#define WARN(...) do{fprintf(stderr,\"WARN:\"); fprintf(stderr,__VA_ARGS__);}while(0) +#define ERROR(...) do{fprintf(stderr,\"ERROR:\"); fprintf(stderr,__VA_ARGS__);}while(0) + +extern int do_set( char** parts, int num_parts, struct trapframe* tf); +extern int do_read( char** parts, int num_parts, struct trapframe* tf); +extern int do_dump( char** parts, int num_parts, struct trapframe* tf); +extern int do_trap( char** parts, int num_parts, struct trapframe* tf); +extern int do_rmc( char** parts, int num_parts, struct trapframe* tf); + +enum command_type {SET_CMD,READ_CMD,DUMP_CMD,TRAP_CMD,RMC_CMD}; + +struct command { + char* name; + enum command_type command_type; + int (*eval)(); +}; + +const struct command commands[]={ + {\"set\", SET_CMD, do_set}, + {\"read\", READ_CMD, do_read}, + {\"dump\", DUMP_CMD, do_dump}, + {\"trap\", TRAP_CMD, do_trap}, + {\"rmc\", RMC_CMD, do_rmc} +}; +#define NUM_COMMANDS (sizeof(commands)/sizeof(struct command)) + +struct named_reg { + char* name; + size_t offset; +}; + +const struct named_reg named_regs[]={ + {\"x0\", offsetof(struct trapframe,x0)}, + {\"x1\", offsetof(struct trapframe,x1)}, + {\"x2\", offsetof(struct trapframe,x2)}, + {\"x3\", offsetof(struct trapframe,x3)}, + {\"x4\", offsetof(struct trapframe,x4)}, + {\"x5\", offsetof(struct trapframe,x5)}, + {\"x6\", offsetof(struct trapframe,x6)}, + {\"x7\", offsetof(struct trapframe,x7)}, + {\"x8\", offsetof(struct trapframe,x8)}, + {\"x9\", offsetof(struct trapframe,x9)}, + {\"x10\", offsetof(struct trapframe,x10)}, + {\"x11\", offsetof(struct trapframe,x11)}, + {\"x12\", offsetof(struct trapframe,x12)}, + {\"x13\", offsetof(struct trapframe,x13)}, + {\"x14\", offsetof(struct trapframe,x14)}, + {\"x15\", offsetof(struct trapframe,x15)}, + {\"x16\", offsetof(struct trapframe,x16)}, + {\"x17\", offsetof(struct trapframe,x17)}, + {\"x18\", offsetof(struct trapframe,x18)}, + {\"x19\", offsetof(struct trapframe,x19)}, + {\"x20\", offsetof(struct trapframe,x20)}, + {\"x21\", offsetof(struct trapframe,x21)}, + {\"x22\", offsetof(struct trapframe,x22)}, + {\"x23\", offsetof(struct trapframe,x23)}, + {\"x24\", offsetof(struct trapframe,x24)}, + {\"x25\", offsetof(struct trapframe,x25)}, + {\"x26\", offsetof(struct trapframe,x26)}, + {\"x27\", offsetof(struct trapframe,x27)}, + {\"x28\", offsetof(struct trapframe,x28)}, + {\"x29\", offsetof(struct trapframe,x29)}, + {\"x30\", offsetof(struct trapframe,x30)}, + {\"sp\", offsetof(struct trapframe,sp)}, + {\"far\", offsetof(struct trapframe,far)}, + {\"esr\", offsetof(struct trapframe,esr)}, + {\"spsr\", offsetof(struct trapframe,spsr)}, + {\"elr\", offsetof(struct trapframe,elr)} +}; + +#define NUM_NAMED_REGS (sizeof(named_regs)/sizeof(struct named_reg)) + +struct rmc_command { + unsigned char class; + unsigned char func; + char* name; +}; + +#define NUM_RMC_COMMANDS (sizeof(rmc_commands)/sizeof(struct rmc_command)) + +const struct rmc_command rmc_commands[]={ +" + +cat $@ |\ +awk '{print tolower($0)}'|\ +sed -e 's/\./\_/'|\ +sed -e 's/\./\_/'|\ +sed -e 's/\(^[0-9]*\)\t\([0-9]*\)\t\([a-z\_\.]*\).*/\t\{\1,\2,"\3"\},/'|\ +sed -e '$ s/.$//' + +echo "};"