cake
/
p7utils
Archived
1
0
Fork 0

Bodged p7os in.

This commit is contained in:
Thomas Touhey 2016-12-22 17:38:55 +01:00
parent 24237160e4
commit 6545ef3546
9 changed files with 452 additions and 4 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "src/p7os/update.exe"]
path = src/p7os/update.exe
url = https://forge.touhey.fr/casio/update.exe

View File

@ -84,13 +84,26 @@ reinstall: uninstall install
$(BINARIES:%=$(OBJDIR)/%):
$(call bcmd,mkdir,$@,$(MD) $@)
# Make an object out of a C source file.
# Make an object out of a source file/directory.
define make-binaryobj-rule
$(OBJDIR)/$1/%.o: $(SRCDIR)/$1/%.c | $(OBJDIR)/$1
ifeq ($(shell test -f $(SRCDIR)/$1/$2.c && echo y),y)
# - Out of a C source file
$(OBJDIR)/$1/$2.o: $(SRCDIR)/$1/$2.c | $(OBJDIR)/$1
$(call bcmd,cc,$$@,$(CC) -c -o $$@ $$< $(CFLAGS))
else
# - Out of an update.exe project
$(SRCDIR)/$1/$2.exe/$2.exe.bin:| $(SRCDIR)/$1/$2.exe
$(call qcmd,cd $$| && ./configure)
$(call bcmd,make,$2.exe,$(MAKE) $$| $2.exe.bin | sed -e 's/^/ /')
$(OBJDIR)/$1/$2.o: $(SRCDIR)/$1/$2.exe/$2.exe.bin | $(OBJDIR)/$1
$(call bcmd,ld -r,$$@,cd $(SRCDIR)/$1/$2.exe && \
$(LDR) -o ../../../$$@ -b binary $2.exe.bin)
endif
endef
$(foreach bin,$(BINARIES),\
$(eval $(call make-binaryobj-rule,$(bin))))
$(foreach obj,$(SRC_$(bin)),\
$(eval $(call make-binaryobj-rule,$(bin),$(obj)))))
# Make a binary
define make-binary-rule

View File

@ -76,6 +76,11 @@
LDFLAGS := $(shell $(PKGCONFIG) --libs $(LIBS) 2>/dev/null) \
$(if $(FOR_WINDOWS),,$(LDFLAGS_Linux))
# Raw ELF object maker
LDR := $(TARGET)ld -r
# Maker
MAKE := make -C
# Directory maker
MD := mkdir -p
# File remover
@ -97,7 +102,9 @@
# Look for their sources
define get-binary-sources
SRC_$1 := $(basename $(shell find $(SRCDIR)/$1 \
-maxdepth 1 -mindepth 1 -type f -name "*.c" -printf "%P\n" | sort))
-maxdepth 1 -mindepth 1 \
\( -name "*.c" -or -name "*.exe" \) \
-printf "%P\n" | sort))
endef
$(foreach bin,$(BINARIES), \
$(eval $(call get-binary-sources,$(bin))))

53
doc/p7os.1.txt Normal file
View File

@ -0,0 +1,53 @@
P7OS(1)
=======
Thomas "Cakeisalie5" Touhey
:Email: thomas@touhey.fr
:man source: p7os
:man manual: p7os manual
NAME
----
p7os - get and change CASIO calculator's OSes using protocol 7
SYNOPSIS
--------
[source,bash]
----
p7os [-h|--help] [-v|--version] [<subcommand> [<args>]]
----
DESCRIPTION
-----------
p7os is a command-line utility to get and upload an OS on CASIO fx calculators,
using its communication protocol 7.00 and OS update mode.
Available submenus are :
*prepare*::
This subcommand must be run before *any* other subcommand. It will upload
a P7 server that supports the commands required by them.
*get [-o os.bin]*::
Get OS image copy.
You have to *prepare* before doing any other action. Preparing means sending
a P7 server on the calculator that will be able to execute commands required
by other subcommands.
OPTIONS
-------
Options start with one or two dashes. Some of the options require an additional
value next to them.
*-h, --help*::
Display command/subcommand help page and quit.
*-v, --version*::
Display version and quit.
*--device /dev/mydevice0*::
The device with which to interact.
Mostly */dev/cfx0* for USB and */dev/ttyS0* for serial connections.
*-o OUT, --output=OUT*::
When getting something, where to store.
SEE ALSO
--------
*libp7*(3)

175
src/p7os/args.c Normal file
View File

@ -0,0 +1,175 @@
/* ************************************************************************** */
/* _____ _ */
/* args.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: p7os | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/09/28 06:00:10 |___/ */
/* */
/* ************************************************************************** */
#include "main.h"
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
/* ************************************************************************** */
/* Help and version messages */
/* ************************************************************************** */
/* The version message - that's when the President comes in */
const char version_message[] =
"P7OS v" QUOTE(VERSION) " (licensed under " QUOTE(LICENSE) ")\n"
"Made by " QUOTE(AUTHOR) " <" QUOTE(AUTHOR_MAIL) ">.\n"
"\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or\n"
"FITNESS FOR A PARTICULAR PURPOSE.";
/* Main help message */
const char help_main[] =
"Usage: p7os [--version|-v] [--help|-h] [--device /dev/omg0]\n"
" <subcommand> [options...]\n"
"\n"
"Subcommands you can use are :\n"
" prepare Prepare server on distant machine\n"
" get Get the OS image\n"
"\n"
"All subcommands that aren't \"prepare\" require \"prepare\" to be run\n"
"before them.\n"
"\n"
"General options:\n"
" -h, --help Display the help page of the (sub)command and quit.\n"
" -v, --version Display the version message and quit.\n"
" --device dev The calculator device (usually /dev/ttyUSBx).\n"
" By default, will use the first appropriate device found.\n"
"\n"
"Type \"p7os <subcommand> --help\" for some help about a subcommand.\n"
"Report bugs to " QUOTE(AUTHOR) " <" QUOTE(AUTHOR_MAIL) ">.";
/* Help message for prepare subcommand */
const char help_prepare[] =
"Usage: p7os prepare\n"
"Send the P7 server on the calculator for further operations.\n"
"This must be used before any other p7os operation.\n"
"\n"
"Type \"p7os --help\" for other subcommands and general options.";
/* Help message for get subcommand */
const char help_get[] =
"Usage: p7os get [-o <os.bin>]\n"
"Get the calculator OS image.\n"
"You must have \"p7os prepare\"-ed before.\n"
"\n"
"Options are :\n"
" -o <os.bin> Where to store the image (default is \"os.bin\")\n"
"\n"
"Type \"p7os --help\" for other subcommands and general options.";
/* ************************************************************************** */
/* Main function */
/* ************************************************************************** */
/* Help macro */
#define ragequit(ARGS, N) { \
if (help || aac != (ARGS)) { \
puts(help_##N); \
return (1); \
} \
}
/**
* parse_args:
* Args parsing main function.
*
* Based on my very first experiment with getopt.
*
* @arg ac the arguments count
* @arg av the arguments values
* @arg args the parsed args pointer
* @return if has been parsed successfully
*/
int parse_args(int ac, char **av, args_t *args)
{
/* initialize args */
*args = (args_t){
.device = NULL,
.local = NULL, .localpath = NULL
};
/* define options */
const char short_options[] = "hvo:";
const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{"device", required_argument, NULL, 'p'},
{"output", required_argument, NULL, 'o'},
{NULL, 0, NULL, 0}
};
/* get all options */
int c; opterr = 0;
int help = 0, version = 0;
const char *s_out = "os.bin";
while ((c = getopt_long(ac, av, short_options, long_options, NULL)) != -1) {
switch (c) {
/* help */
case 'h': help = 1; break;
/* version */
case 'v': version = 1; break;
/* device */
case 'p': args->device = optarg; break;
/* output */
case 'o': s_out = optarg; break;
/* error */
case '?':
if (optopt == 'o')
log("-o, --output: expected an argument\n");
else if (optopt == 'p')
log("--device: expected an argument\n");
else
break;
return (1);
}
}
/* check for version */
if (version) {
puts(version_message);
return (1);
}
/* get non-option arguments (subcommand and parameters) */
int aac = ac - optind;
char **aav = &av[optind];
char *sub = aac ? aav[0] : NULL;
aac--; aav++;
/* subcommand. */
char fpmode[2] = "r";
if (!sub || !strcmp(sub, "help")) {
puts(help_main);
return (1);
} else if (!strcmp(sub, "prepare")) {
ragequit(0, prepare)
} else if (!strcmp(sub, "get")) {
ragequit(0, get)
args->localpath = s_out;
fpmode[0] = 'w';
} else {
log("Unknown subcommand '%s'.\n", aav[0]);
return (1);
}
/* open destination file */
if (args->localpath) {
args->local = fopen(args->localpath, fpmode);
if (!args->local) {
log("Could not open local file: '%s'\n", strerror(errno));
return (1);
}
}
/* everything went well :) */
return (0);
}

112
src/p7os/main.c Normal file
View File

@ -0,0 +1,112 @@
/* ************************************************************************** */
/* _____ _ */
/* main.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: p7os | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/09/28 06:00:10 |___/ */
/* */
/* ************************************************************************** */
#include "main.h"
#include <unistd.h>
/* ************************************************************************** */
/* Error messages */
/* ************************************************************************** */
/* Couldn't initialize connexion to calculator. */
const char error_noconnexion[] =
"Could not connect to the calculator.\n"
"- Is it plugged in and in Receive mode/OS Update?\n"
"- Have you tried changing the cable ?\n";
/* Calculator was found but program wasn't allowed to communicate with it. */
const char error_noaccess[] =
"Could not get access to the calculator.\n"
"Install the appropriate udev rule, or run as root.\n";
/* The calculator acted in a weird way. */
const char error_unplanned[] =
"The calculator didn't act as planned: %s.\n"
"Stop receive mode on calculator and start it again before re-running p7os.\n";
/* Unsupported operation -> OS Update, not receive mode! */
const char error_unsupported[] =
"Required operation was unsupported.\n"
"- If you were using anything else than the *prepare* subcommand, are you\n"
" sure you've run *prepare* before?\n"
"- Otherwise, I gotta be honest, I'd like to know how you've managed that.\n";
/* ************************************************************************** */
/* Main function */
/* ************************************************************************** */
/**
* main:
* User entry point of the program.
*
* @arg ac arguments count
* @arg av arguments values
* @return return code (0 if OK)
*/
int main(int ac, char **av)
{
/* parse args */
args_t args;
if (parse_args(ac, av, &args))
return (0);
/* Initialize libp7 and communication */
p7_handle_t *handle; int err;
if (args.device) err = p7_cinit(&handle, 1, 1, args.device, 0);
else err = p7_init(&handle, 1, 1);
if (err) {
/* displaying error */
switch (err) {
case p7_error_nocalc: log(error_noconnexion);
case p7_error_noaccess: log(error_noaccess);
case p7_error_unsupported: log(error_unsupported);
default: log(error_unplanned, p7_strerror(err));
}
/* closing, removing if necessary */
if (args.localpath) {
fclose(args.local);
remove(args.localpath);
}
return (1);
}
/* check according to menu */
FILE *update_exe;
switch (args.menu) {
/* prepare menu */
case mn_prepare:;
/* open memory stream for the update.exe */
size_t uexe_size = (size_t)&update_exe_end - (size_t)&update_exe_str;
update_exe = fmemopen(update_exe_str, uexe_size, "r");
if (!update_exe) break;
/* send the update.exe */
if ((err = p7_sendexe_stream(handle, update_exe, (p7uint_t)uexe_size,
0x88030000, 0x88030000)))
fprintf(stderr, "An error has occurred: %s\n", p7_strerror(err));
break;
/* get menu */
case mn_get:
/* get the os */
err = !get_os(handle, args.local);
fclose(args.local);
/* if there was an error, delete created file */
if (err) unlink(args.localpath);
break;
}
/* exit libp7
* due to the nature of command 0x56,
* no need to terminate communication! */
p7_exit(handle, 0);
/* then we're good */
return (0);
}

54
src/p7os/main.h Normal file
View File

@ -0,0 +1,54 @@
/* ************************************************************************** */
/* _____ _ */
/* main.h |_ _|__ _ _| |__ ___ _ _ */
/* | Project: p7os | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/09/28 06:00:10 |___/ */
/* */
/* ************************************************************************** */
#ifndef MAIN_H
# define MAIN_H
# include <stdio.h>
# include <libp7.h>
# define Q(x) #x
# define QUOTE(x) Q(x)
# define log(S, ...) fprintf(stderr, S, ##__VA_ARGS__)
/* ************************************************************************** */
/* Embedded update.exe */
/* ************************************************************************** */
#define update_exe_str (_binary_update_exe_bin_start)
#define update_exe_end (_binary_update_exe_bin_end)
extern char _binary_update_exe_bin_start[];
extern char _binary_update_exe_bin_end[];
/* ************************************************************************** */
/* CLI options */
/* ************************************************************************** */
/* Menu */
typedef enum {
mn_prepare,
mn_get
} menu_t;
/* Arguments */
typedef struct {
/* basic things */
menu_t menu;
/* others */
char *device;
FILE *local; const char *localpath;
} args_t;
/* Parsing function */
int parse_args(int ac, char **av, args_t *args);
/* ************************************************************************** */
/* Actual things */
/* ************************************************************************** */
/* Main functions */
int get_os(p7_handle_t *handle, FILE *dest);
#endif /* MAIN_H */

30
src/p7os/stuff.c Normal file
View File

@ -0,0 +1,30 @@
/* ************************************************************************** */
/* _____ _ */
/* stuff.c |_ _|__ _ _| |__ ___ _ _ */
/* | Project: p7os | |/ _ \| | | | '_ \ / _ \ | | | */
/* | | (_) | |_| | | | | __/ |_| | */
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
/* Last updated: 2016/09/28 06:00:10 |___/ */
/* */
/* ************************************************************************** */
#include "main.h"
/**
* get_os:
* Gather the OS.
*
* @arg handle the libp7 handle
* @arg dest the destination file
* @return if it worked
*/
int get_os(p7_handle_t *handle, FILE *dest)
{
/* TODO */
fprintf(stderr, "Unimplemented yet.\n");
(void)handle;
(void)dest;
/* then nothing */
return (0);
}

1
src/p7os/update.exe Submodule

@ -0,0 +1 @@
Subproject commit 787d8bb1083c7608bd62ff06a73b441e920c6105