# fxos fxos is an extended disassembler specifically used to reverse-engineer the OS, bootcode, and syscalls of CASIO fx and fx-CG series. It used to be part of the [fxSDK](/Lephenixnoir/fxsdk). If you have a use for fxos, then be sure to also check the [Planète Casio bible](https://bible.planet-casio.com/), which gathers most of the reverse-engineering knowledge and research of the community. If you're familiar with IDA, Ghidra, or other industry-grade reverse-engineering tools, then fxos won't be able to compete. This is more of a scripting playground with very OS-centric features for me. Some of the things it can do that usual tools might not do directly include: * Finding OS-specific data like bootcode/OS headers/footers, dates, versions * Computing and checking checksums * Analyzing syscall tables and consistently identifying syscall table entries * (TODO) Comparing functions across OS versions to find changes On the other hand, there are no call graph, cross-references, or function type analysis (yet). I have plans for a simple abstract interpreter to bridge some of the gap between pure disassembly and decompilation. fxos runs on Linux and should build successfully on MacOS. If there are compatibility issues with your favorite system, let me know. ## Building fxos is mainly standalone; to build, you will need the following tools. The versions indicated are the ones I use, and clearly not the minimum requirements. * g++ (9.2.0) * flex (2.6.4) * CMake (3.15) and make (eg. 4.2.1) The only real configure option is the install path. CMake's default is `/usr/local`; a viable alternative is `$HOME/.local`. ```sh % cmake -B build # -DCMAKE_INSTALL_PREFIX=$HOME/.local % make -C build -j$(nproc) install ``` ## Setting up the library fxos works with a library of files ranging from OS binaries to assembler instruction tables to scripts. The library is formed of one or more folders defined in the `FXOS_PATH` environment variable. Folders in the path serve two purposes: * Any `fxosrc` file at the root of a folder is executed at startup. * All paths are interpreted relative to the `FXOS_PATH`. Unless you want to redo the research by yourself, I suggest using shared community data from the [fxdoc repository](/Lephenixnoir/fxdoc). New folders could be created easily on the same model; read the `fxosrc` script to see how it is structured. ## Main concepts fxos has a command-line interface *kind of* like rizin. Type `?` to get a list of commands, and any command name followed by `?` to get help on a particular command (eg. `vc?`). The dot command `.` is used to run a script, which is a file with a series of fxos commands. This is used at startup to run every `fxosrc` script found in the `FXOS_PATH`. **Notations** * Identifiers/names are C identifiers but dots (`.`) are allowed. * Usual decimal, hex (`0x`), binary (`0b`) values. * Syscalls are identified with `%`, such as `%01e`. * `$` is the current position in the selected virtual space. * Commands accept arithmetic but only within parentheses; you can write `e (1+2)` but not `e 1+2`. * Ranges can be specified as `:` or `..`. * Paths should use quotes: `"/os/fx/3.10/3.10.bin"`. Only identifiers/names can be written without quotes in commands. * Commands can be chained with `;`. * Anything from a `#` to end of line is a comment. **Virtual spaces** A *virtual space* is an emulation of the calculator's virtual memory. Usually there is one for each OS being studied. Each virtual space has a number of *bindings*, which is a mapping from a virtual address to a file (usually a dump of the calculator's ROM or RAM). Use `vl` to show the virtual spaces and their bindings. The name of the current virtual space is shown in the prompt along with the current position, for instance: ``` cg_3.60 @ 0x80000000> ``` A new empty space can be created with `vc`, and then files can be mapped manually with `vm`. File paths are interpreted relative to `FXOS_PATH` folders even if they start with `/`. Finally, the `vs` command is used to switch between different virtual spaces. **Symbols** Each virtual space can have symbols defined, which are names associated to either addresses or syscall numbers. `ms` will define a new symbol at an explicit address or syscall entry (which is kept symbolic, ie. it will work across different OS versions) and `is` lists all symbols for a virtual space. ## File formats Besides fxos scripts and the actual binary files being used, there is currently only one other type of data file: assembly instruction listings. See `asm/sh3.txt` for an explanation of the syntax; essentially each line has: * The opcode pattern, a 16-character string using `01nmdi`. * A mnemonic. * Zero, one or two arguments among a finite set. Here is an excerpt from the SH-4A extensions table. ``` type: assembly name: sh-4a-extensions --- 0000nnnn01110011 movco.l r0, @rn 0000mmmm01100011 movli.l @rm, r0 0100mmmm10101001 movua.l @rm, r0 0100mmmm11101001 movua.l @rm+, r0 0000nnnn11000011 movca.l r0, @rn ``` Internally, fxos keeps a table with all 65536 opcodes and fills it with instances of instructions described in assembly tables. (TODO) Disassembly listings are intended to be produced and maintained by fxos while still being edited by hand. In order for this to work properly, manual edits should only use `#`-comments, either at the start of a line or with a `#` symbol followed by a space (to distinguish from constants like `#3`): ``` # Set SR.BL = 1 (block interrupt) and SR.IMASK = 0x00*0 (error ?) 4143a: 04 02 stc sr,r4 # get SR register. 4143c: e5 10 mov #16,r5 # r5 = 0x00000010 ``` ## Contributing issues, results, and code Any bug reports, issues and improvement suggestions are welcome. See the [bug tracker](/Lephenixnoir/fxos/issues). If you have reverse-engineering results so share, the best place to do so is on the [Planète Casio bible](https://bible.planet-casio.com). Ping me or Breizh_craft on the Planète Casio shoutbox to have an SSH access set up for you. PRs are also most welcome. Before submitting code, make sure to run `clang-format` to avoid any editor/configuration mishaps: ```sh % clang-format -i include/**/*.h lib/**/*.cpp shell/**/*.cpp ```