From 10357a4ce311a06d09d6fae1acaefaa20c89947a Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 19 Oct 2022 14:53:58 -1000 Subject: [PATCH] SCP: Support running without built-in ROM or other boot code Some potential packaging platforms do not want to package/distribute simh simulators which have build-in binary code (ROM images or other boot code) which may have unknown copyright status. Historically Linux distributed prebuild simulators but left it to a simulator user to reach out on the web to pick up these needed pieces to actually use the simulator(s). This addition allows the default simulator builds to include the needed binary components built into the simulator(s). In addition, it also allows simlators to be built with DONT_USE_INTERNAL_ROM defined and thus not to contain the material with potentially questionalble providence, but to transparently reach out to the web to fetch the needed component(s) when they are needed without any effort on the part of the simulator user. --- scp.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ scp.h | 2 ++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/scp.c b/scp.c index 6be1336a..1b0969f9 100644 --- a/scp.c +++ b/scp.c @@ -8243,12 +8243,21 @@ for (mtab = dptr->modifiers; (mtab != NULL) && (mtab->mstring != NULL); ++mtab) static const unsigned char *mem_data = NULL; static size_t mem_data_size = 0; +static const char *mem_filepath; +static unsigned int mem_checksum; + +t_stat sim_set_memory_load_file_ex (const unsigned char *builtin_code, size_t size, const char *filepath, unsigned int checksum) +{ +mem_data = builtin_code; +mem_data_size = size; +mem_filepath = filepath; +mem_checksum = checksum; +return SCPE_OK; +} t_stat sim_set_memory_load_file (const unsigned char *data, size_t size) { -mem_data = data; -mem_data_size = size; -return SCPE_OK; +return sim_set_memory_load_file_ex (data, size, NULL, 0); } int Fgetc (FILE *f) @@ -8268,16 +8277,20 @@ t_stat load_cmd (int32 flag, CONST char *cptr) { char gbuf[CBUFSIZE]; FILE *loadfile = NULL; -t_stat reason; +t_stat reason = SCPE_OK; GET_SWITCHES (cptr); /* get switches */ if (*cptr == 0) /* must be more */ return SCPE_2FARG; cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */ -if (!mem_data) { +if (mem_data == NULL) { + if (mem_filepath != NULL) + reason = sim_fetch_binary_file (gbuf, mem_filepath, mem_data_size, mem_checksum); + if (reason != SCPE_OK) + return reason; loadfile = sim_fopen (gbuf, flag? "wb": "rb"); /* open for wr/rd */ if (loadfile == NULL) - return SCPE_OPENERR; + return sim_messagef (SCPE_OPENERR, "Error opening '%s' - %s\n", gbuf, strerror (errno)); } GET_SWITCHES (cptr); /* get switches */ reason = sim_load (loadfile, (CONST char *)cptr, gbuf, flag);/* load or dump */ @@ -8286,6 +8299,48 @@ if (loadfile) return reason; } +#define SIM_REPO_PATH "https://github.com/simh/simh/raw/master/" + +t_stat sim_fetch_binary_file (const char *filename, const char *filepath, size_t size, unsigned int checksum) +{ +struct stat filestat; +t_stat r = SCPE_OK; +FILE *f; +t_bool fetched = FALSE; +int byte; +unsigned int thissum = 0; +size_t bytes = 0; + +if (sim_stat (filename, &filestat)) { + char cmd[CBUFSIZE]; + + if ((errno == EACCES) || (errno == EPERM)) + return SCPE_OPENERR; + sim_messagef (SCPE_OK, "Fetching %s from %s%s\n", filename, SIM_REPO_PATH, filepath); + snprintf (cmd, sizeof (cmd), "-LJOs %s%s", SIM_REPO_PATH, filepath); + r = curl_cmd (0, cmd); + if (r != SCPE_OK) + return sim_messagef (SCPE_OPENERR, "Can't acquire '%s' remotely\n", filename); + fetched = TRUE; + } +f = sim_fopen (filename, "rb"); +if (f == NULL) + return sim_messagef (SCPE_OPENERR, "Can't open '%s' - %s\n", filename, strerror (errno)); +while (EOF != (byte = fgetc (f))) { + ++bytes; + thissum += (unsigned char)byte; + } +fclose (f); +thissum = ~thissum; +if (((bytes != size) || (thissum != checksum)) && fetched) + unlink (filename); +if (bytes != size) + return sim_messagef (SCPE_OPENERR, "'%s' Expected file size found %d instead of %d\n", filename, (int)bytes, (int)size); +if (thissum != checksum) + return sim_messagef (SCPE_OPENERR, "'%s' Expected file size found 0x%X instead of 0x%X\n", filename, thissum, checksum); +return SCPE_OK; +} + /* Attach command at[tach] unit file attach specified unit to file diff --git a/scp.h b/scp.h index 5af24b39..620982d3 100644 --- a/scp.h +++ b/scp.h @@ -195,6 +195,7 @@ int Fprintf (FILE *f, const char *fmt, ...) GCC_FMT_ATTR(2, 3); #define fputs(_s,_f) Fprintf(_f,"%s",_s) #define fputc(_c,_f) Fprintf(_f,"%c",_c) t_stat sim_set_memory_load_file (const unsigned char *data, size_t size); +t_stat sim_set_memory_load_file_ex (const unsigned char *data, size_t size, const char *filepath, unsigned int checksum); int Fgetc (FILE *f); t_stat fprint_val (FILE *stream, t_value val, uint32 rdx, uint32 wid, uint32 fmt); t_stat sprint_val (char *buf, t_value val, uint32 rdx, uint32 wid, uint32 fmt); @@ -241,6 +242,7 @@ t_stat sim_exp_showall (FILE *st, const EXPECT *exp); t_stat sim_exp_check (EXPECT *exp, uint8 data); CONST char *match_ext (CONST char *fnam, const char *ext); int sim_cmp_string (const char *s1, const char *s2); +t_stat sim_fetch_binary_file (const char *filename, const char *filepath, size_t size, unsigned int checksum); t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat set_dev_debug (DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat show_dev_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr);