Vhex v2 - add-in redisign: Add minimal kernel and minimal libs

This commit is contained in:
Yann MAGNIN 2019-12-02 16:48:36 +01:00
parent ace25fd496
commit 84efc8c451
73 changed files with 1870 additions and 1933 deletions

3
.gitignore vendored
View File

@ -55,3 +55,6 @@ dkms.conf
# Other
*.txt
build/
debug
.tests
.old

128
Makefile
View File

@ -1,64 +1,93 @@
#!/usr/bin/make -f
# ---
# Project: FIXME WRITE DOC !!
# Author: yann.magnin@epitech.eu
# ---
include global.mk
## ---
## Project: sprite-coder
## Author:
## theo.cousinet@epitech.eu
## yann.magnin@epitech.eu
## ---
NAME := vhex
EXEC := $(NAME).g1a
HEADER := -Iinclude
DEBUG := link_map.txt
LDFLAG := -T bootstrap.ld
ICON := icon.bmp
BUILD := build/
##---
## Static variables
##--
HEADER := include
BUILD := build
DEBUG := debug
NAME := vhex
EXEC := $(NAME).g1a
LDFLAG := -T $(NAME).ld
MEMORY_MAP := $(DEBUG)/$(NAME).map
ICON := icon.bmp
COMPILER := sh3eb-elf-
CC := $(COMPILER)gcc
OBJCOPY := $(COMPILER)objcopy
WRAPPER := g1a-wrapper
CFLAGS := -Werror -Wall -W -Wextra -std=c18 -m3 -mb -mrenesas \
-ffreestanding -nostdlib -fstrict-volatile-bitfields \
-Wno-unused-const-variable -Wno-unused-function \
-Wno-unused-variable -Wno-unused-but-set-variable \
-Wno-unused-parameter
red := \033[1;31m
green := \033[1;32m
blue := \033[1;34m
white := \033[1;37m
nocolor := \033[1;0m
##---
## Automated variables
##---
SRC :=
DIRECTORY := src/ $(sort $(dir $(wildcard src/*/*/)))
DIRECTORY := $(shell find src -not -path "*/\.*" -type d)
# Get all source files
$(foreach path,$(DIRECTORY),$(eval \
SRC += $(wildcard $(path)*.c) \
$(wildcard $(path)*.s) \
$(wildcard $(path)*.S)) \
)
OBJ := $(patsubst src_%,$(BUILD)%.o,$(subst /,_,$(basename $(SRC))))
SRC += $(wildcard $(path)/*.c) \
$(wildcard $(path)/*.S) \
$(wildcard $(path)/*.s) \
))
# Geneate all object files
OBJ := $(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
#all: ;@echo $(SRC) $(OBJ)
all: | $(BUILD) $(EXEC)
install: $(EXEC)
sudo p7 send $<
##---
## General rules
##---
all: | $(BUILD) $(DEBUG) $(EXEC)
$(EXEC): $(OBJ)
@ printf "$(green)/-------\n/ Link files\n/-------$(nocolor)\n"
$(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(BUILD)$(NAME).elf $^ $(HEADER) -lgcc > $(DEBUG)
$(OBJCPY) -R .comment -R .bss -O binary $(BUILD)$(NAME).elf $(BUILD)$(NAME).bin
$(WRAPPER) $(BUILD)$(NAME).bin -o $@ -i $(ICON)
$(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) -I $(HEADER) -lgcc > $(MEMORY_MAP)
$(OBJCOPY) -R .comment -R .bss -O binary $(DEBUG)/$(NAME).elf $(DEBUG)/$(NAME).bin
$(WRAPPER) $(DEBUG)/$(NAME).bin -o $@ -i $(ICON)
$(BUILD):
$(BUILD) $(DEBUG):
@ printf "Create $(blue)$@$(nocolor) directory\n"
@ mkdir -p $@
install: $(EXEC)
sudo p7 send --force $^
#
# TODO: find better way to do the job
# Units tests part.
#
tests:
gcc -std=c11 -Wall -Wno-error=deprecated-declarations -Wno-deprecated-declarations \
-Werror -D DEBUG -o unit_tests $(HEADER) -I. src/history.c src/string/strtotab.c \
src/string/atoi_base.c $(wildcard tests/*.c) --coverage -lcriterion
./unit_tests
gcovr --exclude tests/ --branches
rm *.gc*
rm ./unit_tests
check:
@ echo 'src: $(SRC)'
@ echo 'obj: $(OBJ)'
@ echo 'directory: $(DIRECTORY)'
##---
## Automated rules
##---
define rule-src
$(patsubst src_%,$(BUILD)%.o,$(subst /,_,$(basename $1))): $1
$(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ $(CC) $(CFLAGS) -o $$@ -c $$< -I $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"
endef
@ -67,19 +96,16 @@ $(foreach source,$(SRC),$(eval \
)
#---
# Clean rules
#---
##---
## Cleaning rules
##---
clean:
@ printf "$(red)Delete objects files$(nocolor)\n"
rm -rf $(BUILD)
rm -f *.gc*
rm -f $(DEBUG)
rm -f $(NAME).bin
rm -f $(NAME).elf
rm -rf $(DEBUG)
fclean: clean
@ printf "$(red)Delete binary files$(nocolor)\n"
rm -f $(EXEC)
re: fclean all
@ -87,4 +113,4 @@ re: fclean all
.PHONY: clean re fclean install tests
.PHONY: re fclean clean all install

View File

@ -1,52 +0,0 @@
OUTPUT_ARCH(sh3)
OUTPUT_FORMAT(elf32-sh)
ENTRY(_initialize)
MEMORY
{
rom : o = 0x00300200, l = 512k
ram : o = 0x08100000, l = 8k
}
SECTIONS
{
. = ORIGIN(rom);
.pretext : {
*(.pretext.entry)
*(.pretext)
} > rom
.text : {
*(.text)
} > rom
.rodata : SUBALIGN(4) {
*(.rodata)
. = ALIGN(4);
_bcmd_cache = . ;
*(.cmd.cache)
_ecmd_cache = . ;
} > rom
. = ORIGIN(ram);
.bss (NOLOAD) : {
_bbss = . ;
*(.bss)
*(COMMON)
} > ram : NONE
_sbss = SIZEOF(.bss);
.data ALIGN(4) : ALIGN(4) {
_bdata_rom = LOADADDR(.data) ;
_bdata_ram = . ;
*(.data)
} > ram AT> rom
_sdata = SIZEOF(.data) ;
/* unused sections */
/DISCARD/ : {
*(.comment)
*(.comment.*)
}
}

View File

@ -1,28 +0,0 @@
# Global options, used in each Makefile in the project
# If you have to change a tool name, or to add an option
# for every part of the project, this is the good place.
COMPILER := sh3eb-elf-
CC := $(COMPILER)gcc
OBJCPY := $(COMPILER)objcopy
AR := $(COMPILER)ar
LD := $(COMPILER)ld
WRAPPER := g1a-wrapper
CFLAGS := -Werror -Wall -W -Wextra -std=c18 -m3 -mb -mrenesas \
-ffreestanding -nostdlib -fstrict-volatile-bitfields \
-Wno-unused-const-variable
BUILD-DIR := build/
SRC-DIR := src/
red := \033[1;31m
green := \033[1;32m
blue := \033[1;34m
white := \033[1;37m
nocolor := \033[1;0m
define n
# Force new line character
endef

10
include/kernel/atomic.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __KERNEL_ATOMIC_H__
# define __KERNEL_ATOMIC_H__
#include <stddef.h>
#include <stdint.h>
extern void atomic_start(void);
extern void atomic_end(void);
#endif /*__KERNEL_ATOMIC_H__*/

View File

@ -0,0 +1,9 @@
#ifndef __KERNEL_ARCH_ATTRIBUTES_H__
# define __KERNEL_ARCH_ATTRIBUTES_H__
// Generate "anonyme name" for each gaps.
#define gap_name2(name) _##name
#define gap_name(name) gap_name2(name)
#define GAPS(bytes) const uint8_t gap_name(__LINE__)[bytes]
#endif /*__KERNEL_ARCH_ATTRIBUTES_H__*/

40
include/kernel/context.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef __KERNEL_CONTEXT_H__
# define __KERNEL_CONTEXT_H__
#include <stddef.h>
#include <stdint.h>
typedef struct fx9860_context_s
{
struct {
uint16_t control;
uint16_t autofix;
uint16_t scan_mode;
uint16_t scan_state;
uint16_t interrupt;
uint16_t scan_wait;
uint16_t scan_interval;
uint16_t kyoutdr;
uint16_t kyindr;
} keyboard;
struct {
uint16_t ipra;
uint16_t iprb;
uint16_t iprc;
uint16_t iprd;
uint16_t ipre;
uint16_t iprf;
uint16_t iprg;
uint16_t iprh;
uint16_t ipri;
uint16_t iprj;
uint16_t iprk;
uint16_t iprl;
} intc;
} fx9860_context_t;
// Context primitive.
extern void fx9860_context_save(fx9860_context_t *context);
extern void fx9860_context_restore(fx9860_context_t *context);
#endif /*__KERNEL_CONTEXT_H__*/

View File

@ -0,0 +1,514 @@
#ifndef __KERNEL_MODULES_SH7724_INTC_H__
# define __KERNEL_MODULES_SH7724_INTC_H__
#include <stdint.h>
#include <stddef.h>
#include <kernel/union_types.h>
#include <kernel/attributes.h>
struct SH7305_intc_s
{
//---
// Interrupt priority register.
//---
volatile word_union(IPRA,
uint8_t TMU0_0 : 4; /* Timer 0 */
uint8_t TMU0_1 : 4; /* Timer 1 */
uint8_t TMU0_2 : 4; /* Timer 2 */
uint8_t IrDA : 4; /* Infrared Communication */
);
GAPS(2);
volatile word_union(IPRB,
uint8_t const : 4;
uint8_t LCDC : 4; /* LCD Controller */
uint8_t DMAC1A : 4; /* Direct Memory Controller 1 */
uint8_t const : 4;
);
GAPS(2);
volatile word_union(IPRC,
uint8_t TMU1_0 : 4; /* TMU1 Channel 0 */
uint8_t TMU1_1 : 4; /* TMU1 Channel 1 */
uint8_t TMU1_2 : 4; /* TMU1 Channel 2 */
uint8_t const : 4;
);
GAPS(2);
volatile word_union(IPRD,
uint8_t const : 4;
uint8_t MMCIF : 4; /* MultiMedia Card Interface */
uint8_t const : 4;
uint8_t const : 4;
);
GAPS(2);
volatile word_union(IPRE,
uint8_t DMAC0A : 4; /* Direct Memory Controller 1 */
uint8_t const : 4;
uint8_t const : 4; /* Extra TMU ?? */
uint8_t const : 4;
);
GAPS(2);
volatile word_union(IPRF,
uint8_t KEYSC : 4; /* Key Scan Interface */
uint8_t DMAC0B : 4; /* Direct Memory transfer / error info */
uint8_t USB0_1 : 4; /* USB Controller */
uint8_t CMT : 4; /* Compare Match Timer*/
);
GAPS(2);
volatile word_union(IPRG,
uint8_t SCIF0 : 4; /* SCIF0 transfert / error info */
uint8_t const : 4; /* Extra TMU ?? */
uint8_t const : 4; /* Extra TMU ?? */
uint8_t const : 4;
);
GAPS(2);
volatile word_union(IPRH,
uint8_t MSIOF0 : 4; /* Clock-synchronized SCIF channel 0 */
uint8_t MSIOF1 : 4; /* Clock-synchronized SCIF channel 1 */
uint8_t const : 4;
uint8_t const : 4;
);
GAPS(2);
volatile word_union(IPRI,
uint8_t const : 4; /* Extra TMU ?? */
uint8_t const : 4;
uint8_t const : 4;
uint8_t const : 4;
);
GAPS(2);
volatile word_union(IPRJ,
uint8_t const : 4; /* Extra TMU ?? */
uint8_t const : 4;
uint8_t FSI : 4; /* FIFO - buffered Serial Interface */
uint8_t SDHI1 : 4; /* SD Card Host channel 1 */
);
GAPS(2);
volatile word_union(IPRK,
uint8_t RTC : 4; /* Real Time Clock */
uint8_t DMAC1B : 4; /* DMAC1 transfer/error info */
uint8_t const : 4;
uint8_t SDHI0 : 4; /* SD Card Host channel 0 */
);
GAPS(2);
volatile word_union(IPRL,
uint8_t const : 4; /* Extra TMU ?? */
uint8_t const : 4;
uint8_t TPU : 4; /* Timer-Pulse Unit */
uint8_t const : 4;
);
GAPS(0x52);
//---
// Interrupt mask register.
// FIXME
// This is the SH7224 Interrupt mask registers, so find
// the interrupt mask regiters for the SH7305.
//---
volatile byte_union(IMR0,
uint8_t const : 1;
uint8_t TUNI2 : 1; /* TMU1 (timer2) */
uint8_t TUNI1 : 1; /* TMU1 (timer1) */
uint8_t TUNI0 : 1; /* TMU1 (timer0) */
uint8_t SDHII3 : 1; /* SDHI1 */
uint8_t SDHII2 : 1; /* SDHI1 */
uint8_t SDHII1 : 1; /* SDHI1 */
uint8_t SDHII0 : 1; /* SDHI1 */
);
GAPS(3);
volatile byte_union(IMR1,
uint8_t VOUI : 1; /* VIO */
uint8_t VEU1I : 1; /* VIO */
uint8_t BEU0I : 1; /* VIO */
uint8_t CEU0I : 1; /* VIO */
uint8_t DEI3 : 1; /* DMAC0A */
uint8_t DEI2 : 1; /* DMAC0A */
uint8_t DEI1 : 1; /* DMAC0A */
uint8_t DEI0 : 1; /* DMAC0A */
);
GAPS(3);
volatile byte_union(IMR2,
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t VPUI : 1; /* VPU */
uint8_t ATAPI : 1; /* ATAPI */
uint8_t EtherMAC: 1; /* Ether */
uint8_t const : 1;
uint8_t SCIFA0 : 1; /* SCIFA0 */
);
GAPS(3);
volatile byte_union(IMR3,
uint8_t DEI3 : 1; /* DMAC1A */
uint8_t DEI2 : 1; /* DMAC1A */
uint8_t DEI1 : 1; /* DMAC1A */
uint8_t DEI0 : 1; /* DMAC1A */
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t IRDAI : 1; /* IrDA */
);
GAPS(3);
volatile byte_union(IMR4,
uint8_t const : 1;
uint8_t TUNI2 : 1; /* TMU0 (timer2) */
uint8_t TUNI1 : 1; /* TMU0 (timer1) */
uint8_t TUNI0 : 1; /* TMU0 (timer0) */
uint8_t JPUI : 1; /* JPU */
uint8_t const : 1;
uint8_t const : 1;
uint8_t LCDCI : 1; /* LCDC */
);
GAPS(3);
volatile byte_union(IMR5,
uint8_t KEYI : 1; /* KEYSC */
uint8_t DADERR : 1; /* DMAC0B */
uint8_t DEI5 : 1; /* DMAC0B */
uint8_t DEI4 : 1; /* DMAC0B */
uint8_t VEU0I : 1; /* VEU3F0 */
uint8_t SCIF2 : 1; /* SCIF */
uint8_t SCIF1 : 1; /* SCIF */
uint8_t SCIF0 : 1; /* SCIF */
);
GAPS(3);
volatile byte_union(IMR6,
uint8_t const : 1;
uint8_t const : 1;
uint8_t ICBI : 1; /* ICB */
uint8_t SCIFA4 : 1; /* SCIFA4 */
uint8_t CEU1I : 1; /* CEU1 */
uint8_t const : 1;
uint8_t MSIOFI1 : 1; /* MSIOF */
uint8_t MSIOFI0 : 1; /* MSIOF */
);
GAPS(3);
volatile byte_union(IMR7,
uint8_t DTE0I : 1; /* I2C0 */
uint8_t WAITT0I : 1; /* I2C0 */
uint8_t TACK0I : 1; /* I2C0 */
uint8_t AL0I : 1; /* I2C0 */
uint8_t DTE1I : 1; /* I2C1 */
uint8_t WAITT1I : 1; /* I2C1 */
uint8_t TACK1I : 1; /* I2C1 */
uint8_t AL1I : 1; /* I2C1 */
);
GAPS(3);
volatile byte_union(IMR8,
uint8_t SDHII3 : 1; /* SDHI0 */
uint8_t SDHII2 : 1; /* SDHI0 */
uint8_t SDHII1 : 1; /* SDHI0 */
uint8_t SDHII0 : 1; /* SDHI0 */
uint8_t const : 1;
uint8_t const : 1;
uint8_t SCIFA5 : 1; /* SCIFA5 */
uint8_t FSI : 1; /* FSI */
);
GAPS(3);
volatile byte_union(IMR9,
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t CMTI : 1; /* CMT */
uint8_t const : 1;
uint8_t USI1 : 1; /* USB */
uint8_t USI0 : 1; /* USB */
uint8_t const : 1;
);
GAPS(3);
volatile byte_union(IMR10,
uint8_t const : 1;
uint8_t DADERR : 1; /* DMAC1B */
uint8_t DEI5 : 1; /* DMAC1B */
uint8_t DEI4 : 1; /* DMAC1B */
uint8_t const : 1;
uint8_t ATI : 1; /* RTC */
uint8_t PRI : 1; /* RTC */
uint8_t CUI : 1; /* RTC */
);
GAPS(3);
volatile byte_union(IMR11,
uint8_t BRK : 1; /* 2DG */
uint8_t CEI : 1; /* 2DG */
uint8_t INI : 1; /* 2DG */
uint8_t TRI : 1; /* 2DG */
uint8_t const : 1;
uint8_t TPUI : 1; /* TPU */
uint8_t LMBI : 1; /* ICB */
uint8_t TSIFI : 1; /* TSIF */
);
GAPS(3);
volatile byte_union(IMR12,
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t _2DDMAC : 1; /* 2DDMAC */
);
GAPS(15);
//---
// Interrupt clear mask register.
// FIXME
// This is the SH7224 Interrupt mask registers, so find
// the interrupt mask regiters for the SH7305.
//---
volatile byte_union(IMCR0,
uint8_t const : 1;
uint8_t TUNI2 : 1; /* TMU1 (timer2) */
uint8_t TUNI1 : 1; /* TMU1 (timer1) */
uint8_t TUNI0 : 1; /* TMU1 (timer0) */
uint8_t SDHII3 : 1; /* SDHI1 */
uint8_t SDHII2 : 1; /* SDHI1 */
uint8_t SDHII1 : 1; /* SDHI1 */
uint8_t SDHII0 : 1; /* SDHI1 */
);
GAPS(3);
volatile byte_union(IMCR1,
uint8_t VOUI : 1; /* VIO */
uint8_t VEU1I : 1; /* VIO */
uint8_t BEU0I : 1; /* VIO */
uint8_t CEU0I : 1; /* VIO */
uint8_t DEI3 : 1; /* DMAC0A */
uint8_t DEI2 : 1; /* DMAC0A */
uint8_t DEI1 : 1; /* DMAC0A */
uint8_t DEI0 : 1; /* DMAC0A */
);
GAPS(3);
volatile byte_union(IMCR2,
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t VPUI : 1; /* VPU */
uint8_t ATAPI : 1; /* ATAPI */
uint8_t EtherMAC: 1; /* Ether */
uint8_t const : 1;
uint8_t SCIFA0 : 1; /* SCIFA0 */
);
GAPS(3);
volatile byte_union(IMCR3,
uint8_t DEI3 : 1; /* DMAC1A */
uint8_t DEI2 : 1; /* DMAC1A */
uint8_t DEI1 : 1; /* DMAC1A */
uint8_t DEI0 : 1; /* DMAC1A */
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t IRDAI : 1; /* IrDA */
);
GAPS(3);
volatile byte_union(IMCR4,
uint8_t const : 1;
uint8_t TUNI2 : 1; /* TMU0 (timer2) */
uint8_t TUNI1 : 1; /* TMU0 (timer1) */
uint8_t TUNI0 : 1; /* TMU0 (timer0) */
uint8_t JPUI : 1; /* JPU */
uint8_t const : 1;
uint8_t const : 1;
uint8_t LCDCI : 1; /* LCDC */
);
GAPS(3);
volatile byte_union(IMCR5,
uint8_t KEYI : 1; /* KEYSC */
uint8_t DADERR : 1; /* DMAC0B */
uint8_t DEI5 : 1; /* DMAC0B */
uint8_t DEI4 : 1; /* DMAC0B */
uint8_t VEU0I : 1; /* VEU3F0 */
uint8_t SCIF2 : 1; /* SCIF */
uint8_t SCIF1 : 1; /* SCIF */
uint8_t SCIF0 : 1; /* SCIF */
);
GAPS(3);
volatile byte_union(IMCR6,
uint8_t const : 1;
uint8_t const : 1;
uint8_t ICBI : 1; /* ICB */
uint8_t SCIFA4 : 1; /* SCIFA4 */
uint8_t CEU1I : 1; /* CEU1 */
uint8_t const : 1;
uint8_t MSIOFI1 : 1; /* MSIOF */
uint8_t MSIOFI0 : 1; /* MSIOF */
);
GAPS(3);
volatile byte_union(IMCR7,
uint8_t DTE0I : 1; /* I2C0 */
uint8_t WAITT0I : 1; /* I2C0 */
uint8_t TACK0I : 1; /* I2C0 */
uint8_t AL0I : 1; /* I2C0 */
uint8_t DTE1I : 1; /* I2C1 */
uint8_t WAITT1I : 1; /* I2C1 */
uint8_t TACK1I : 1; /* I2C1 */
uint8_t AL1I : 1; /* I2C1 */
);
GAPS(3);
volatile byte_union(IMCR8,
uint8_t SDHII3 : 1; /* SDHI0 */
uint8_t SDHII2 : 1; /* SDHI0 */
uint8_t SDHII1 : 1; /* SDHI0 */
uint8_t SDHII0 : 1; /* SDHI0 */
uint8_t const : 1;
uint8_t const : 1;
uint8_t SCIFA5 : 1; /* SCIFA5 */
uint8_t FSI : 1; /* FSI */
);
GAPS(3);
volatile byte_union(IMCR9,
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t CMTI : 1; /* CMT */
uint8_t const : 1;
uint8_t USI1 : 1; /* USB */
uint8_t USI0 : 1; /* USB */
uint8_t const : 1;
);
GAPS(3);
volatile byte_union(IMCR10,
uint8_t const : 1;
uint8_t DADERR : 1; /* DMAC1B */
uint8_t DEI5 : 1; /* DMAC1B */
uint8_t DEI4 : 1; /* DMAC1B */
uint8_t const : 1;
uint8_t ATI : 1; /* RTC */
uint8_t PRI : 1; /* RTC */
uint8_t CUI : 1; /* RTC */
);
GAPS(3);
volatile byte_union(IMCR11,
uint8_t BRK : 1; /* 2DG */
uint8_t CEI : 1; /* 2DG */
uint8_t INI : 1; /* 2DG */
uint8_t TRI : 1; /* 2DG */
uint8_t const : 1;
uint8_t TPUI : 1; /* TPU */
uint8_t LMBI : 1; /* ICB */
uint8_t TSIFI : 1; /* TSIF */
);
GAPS(3);
volatile byte_union(IMCR12,
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t const : 1;
uint8_t _2DDMAC : 1; /* 2DDMAC */
);
GAPS(0xbff0e);
//---
// Interrupt Control registers 0
//---
volatile word_union(ICR0,
uint8_t NMIL :1; /* Non Maskable Interrupt Input level */
uint8_t MAI :1; /* Non Maskable Interrupt interrupt Mask */
uint8_t const :4; /* All 0 */
uint8_t NMIB :1; /* Non Maskable Interrupt Block Mode */
uint8_t NMIE :1; /* Non Maskable Interrupt Edge Select */
uint8_t const :2; /* All 1 */
uint8_t LVLMODE :1; /* Interrupt Source Retention Mode */
uint8_t const :5; /* All 0 */
);
GAPS(0x0e);
//---
// Interrupt Priority registers
//---
volatile long_union(INTPRI00,
uint32_t IRQ0 : 4; /* Interrupt Request 0 */
uint32_t IRQ1 : 4; /* Interrupt Request 1 */
uint32_t IRQ2 : 4; /* Interrupt Request 2 */
uint32_t IRQ3 : 4; /* Interrupt Request 3 */
uint32_t IRQ4 : 4; /* Interrupt Request 4 */
uint32_t IRQ5 : 4; /* Interrupt Request 5 */
uint32_t IRQ6 : 4; /* Interrupt Request 6 */
uint32_t IRQ7 : 4; /* Interrupt Request 7 */
);
GAPS(8);
//---
// Interrupt Control register 1
//---
volatile word_union(ICR1,
uint8_t IRQ0S :2; /* Interrupt Request 0 Sense Select */
uint8_t IRQ1S :2; /* Interrupt Request 1 Sense Select */
uint8_t IRQ2S :2; /* Interrupt Request 2 Sense Select */
uint8_t IRQ3S :2; /* Interrupt Request 3 Sense Select */
uint8_t IRQ4S :2; /* Interrupt Request 4 Sense Select */
uint8_t IRQ5S :2; /* Interrupt Request 5 Sense Select */
uint8_t IRQ6S :2; /* Interrupt Request 6 Sense Select */
uint8_t IRQ7S :2; /* Interrupt Request 7 Sense Select */
);
GAPS(6);
//---
// Interrupt request register.
//---
volatile byte_union(INTREQ00,
uint8_t IRQ0 : 1; /* Interrupt Request 0 */
uint8_t IRQ1 : 1; /* Interrupt Request 1 */
uint8_t IRQ2 : 1; /* Interrupt Request 2 */
uint8_t IRQ3 : 1; /* Interrupt Request 3 */
uint8_t IRQ4 : 1; /* Interrupt Request 4 */
uint8_t IRQ5 : 1; /* Interrupt Request 5 */
uint8_t IRQ6 : 1; /* Interrupt Request 6 */
uint8_t IRQ7 : 1; /* Interrupt Request 7 */
);
GAPS(0x1f);
//---
// Interrupt mask register.
//---
volatile byte_union(INTMSK00,
uint8_t IRQ0 : 1; /* Interrupt Request 0 */
uint8_t IRQ1 : 1; /* Interrupt Request 1 */
uint8_t IRQ2 : 1; /* Interrupt Request 2 */
uint8_t IRQ3 : 1; /* Interrupt Request 3 */
uint8_t IRQ4 : 1; /* Interrupt Request 4 */
uint8_t IRQ5 : 1; /* Interrupt Request 5 */
uint8_t IRQ6 : 1; /* Interrupt Request 6 */
uint8_t IRQ7 : 1; /* Interrupt Request 7 */
);
GAPS(0x1f);
//---
// Interrupt mask clear register. (write only).
//---
volatile byte_union(INTMSKCLR00,
uint8_t IRQ0 : 1; /* Interrupt Request 0 */
uint8_t IRQ1 : 1; /* Interrupt Request 1 */
uint8_t IRQ2 : 1; /* Interrupt Request 2 */
uint8_t IRQ3 : 1; /* Interrupt Request 3 */
uint8_t IRQ4 : 1; /* Interrupt Request 4 */
uint8_t IRQ5 : 1; /* Interrupt Request 5 */
uint8_t IRQ6 : 1; /* Interrupt Request 6 */
uint8_t IRQ7 : 1; /* Interrupt Request 7 */
);
GAPS(0x5b);
//---
// Non Maskable Interrupt flags control register
//---
volatile word_union(NMIFCR,
uint16_t const NMIL : 1; /* NMI input Level */
uint16_t const : 14; /* All 0 */
uint16_t NMIFL : 1; /* NMI Interrupt Request Detection */
);
GAPS(0x5bff3e);
//---
// User interrupt mask level register.
//---
volatile long_union(USERMSK,
uint32_t SECRET : 8; /* Only write 0xa5 */
uint32_t const : 8; /* All 0 */
uint32_t UIMASK : 4; /* User Interrupt Mask Level */
uint32_t const : 4; /* All 0 */
);
};
#define SH7305_INTC (*(volatile struct SH7305_intc_s *)0xa4080000)
#endif /*__KERNEL_MODULES_SH7724_INTC_H__*/

View File

@ -0,0 +1,66 @@
#ifndef __KERNEL_MODULES_SH7724_KEYSC_H__
# define __KERNEL_MODULES_SH7724_KEYSC_H__
#include <stdint.h>
#include <stddef.h>
#include <kernel/union_types.h>
#include <kernel/attributes.h>
struct sh7305_keysc_s
{
volatile const uint16_t KIUDATA[6];
volatile word_union(CONTROL,
uint16_t KEYIE : 1; /* Key Interrupt enable */
uint16_t const :13; /* All 0 */
uint16_t INTMODE : 2; /* Key Interrupt mode (?) */
);
volatile word_union(AUTOFIX,
uint16_t ENABLE : 1; /* enable AUTOFIX (?) */
uint16_t const : 8; /* All 0 */
uint16_t UNKNOWN0 : 3; /* ????? */
uint16_t const : 1; /* All 0 */
uint16_t UNKNOWN1 : 3; /* ????? */
);
volatile word_union(SCAN_MODE,
uint16_t UNKNOWN0 : 3; /* Scan Timing (?) */
uint16_t UNKNOWN1 : 3; /* Scan mode (?) */
uint16_t const : 10; /* All 0 */
);
volatile word_union(SCAN_STATE,
uint16_t const :15; /* All 0 */
uint16_t STATE : 1; /* ????? */
);
volatile word_union(INTERRUPT,
uint16_t const : 1; /* All 0 */
uint16_t KYCPU_IE : 7; /* KEYSC interrupt setup (see Planet Casio's bible) */
uint16_t const STATUS : 8; /* Indicate the "type" of interruption (pressed, released, etc) */
);
volatile word_union(SCAN_WAIT,
uint16_t const : 1; /* All 0 */
uint16_t TIME :15; /* Time between interrupt */
);
volatile uint16_t SCAN_INTERVAL;
volatile word_union(KYOUTDR,
uint16_t const : 4; /* All 0 */
uint16_t KYO5DT : 2; /* Key Controll ouput 5 */
uint16_t KYO4DT : 2; /* Key Controll ouput 4 */
uint16_t KYO3DT : 2; /* Key Controll ouput 3 */
uint16_t KYO2DT : 2; /* Key Controll ouput 2 */
uint16_t KYO1DT : 2; /* Key Controll ouput 1 */
uint16_t KYO0DT : 2; /* Key Controll ouput 0 */
);
volatile word_union(KYINDR,
uint16_t const : 8; /* All 0 */
uint16_t KYDIR6 : 1; /* Key Direction 6 */
uint16_t KYDIR5 : 1; /* Key Direction 5 */
uint16_t KYDIR4 : 1; /* Key Direction 4 */
uint16_t KYDIR3 : 1; /* Key Direction 3 */
uint16_t KYDIR2 : 1; /* Key Direction 2 */
uint16_t KYDIR1 : 1; /* Key Direction 1 */
uint16_t KYDIR0 : 1; /* Key Direction 0 */
);
};
#define SH7305_KEYSC (*(volatile struct sh7305_keysc_s *)0xa44b0000)
#endif /*__KERNEL_MODULES_SH7724_KEYSC_H__*/

View File

@ -0,0 +1,10 @@
#ifndef __KERNEL_HARDWARE_T6K11_H__
# define __KERNEL_HARDWARE_T6K11_H__
#include <stddef.h>
#include <stdint.h>
// Screen primitive
extern void t6k11_display(void *vram);
#endif /*__KERNEL_HARDWARE_T6K11_H__*/

25
include/kernel/tty.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef __KERNEL_TTY_H__
# define __KERNEL_TTY_H__
#include <stddef.h>
#include <stdint.h>
struct tty_s
{
struct {
uint8_t x;
uint8_t y;
struct {
uint8_t x;
uint8_t y;
} max;
} cursor;
};
// primitives.
extern int tty_open(void);
extern int tty_write(char const *buffer, ...);
//extern void tty_read(char *buffer, size_t count);
extern int tty_close(void);
#endif /*__KERNEL_TTY_H__*/

View File

@ -16,6 +16,16 @@ typedef int32_t ssize_t;
# define __ssize_t_defined
#endif
// Define MPU arch.
typedef enum mpu_e
{
MPU_SH7305,
MPU_SH7724,
MPU_SH7337,
MPU_SH7355,
MPU_UNKNOWN,
} mpu_t;
// Force inline function.
#define INLINE __attribute__((always_inline)) inline

View File

@ -0,0 +1,32 @@
#ifndef __KERNEL_MODULES_TYPES_H__
# define __KERNEL_MODULES_TYPES_H__
#include <stdint.h>
#include <stddef.h>
#define byte_union(name, fields) \
union { \
uint8_t BYTE; \
struct { \
fields \
} __attribute__((packed, aligned(1))); \
} __attribute__((packed, aligned(1))) name
#define word_union(name, fields) \
union { \
uint16_t WORD; \
struct { \
fields \
} __attribute__((packed, aligned(2))); \
} __attribute__((packed, aligned(2))) name
#define long_union(name, fields) \
union { \
uint32_t LONG_WORD; \
struct { \
fields \
} __attribute__((packed, aligned(4))); \
} __attribute__((packed, aligned(4))) name
#endif /*__KERNEL_MODULES_TYPES_H__*/

32
include/lib/display.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef __LIB_DISPLAY_H__
# define __LIB_DISPLAY_H__
#include <stddef.h>
#include <stdint.h>
// Define font bitmap informations.
#define KERNEL_FONT_BITMAP_WIDTH 127 // Bitmap width
#define KERNEL_FONT_BITMAP_HEIGHT 23 // Bitmap height
#define KERNEL_FONT_BITMAP_CWIDTH 4 // Character width (bitmap)
#define KERNEL_FONT_BITMAP_CHEIGHT 6 // Character height (bitmap)
#define KERNEL_FONT_REAL_WIDTH 3 // Charater width (real)
#define KERNEL_FONT_REAL_HEIGHT 5 // Character height (real)
#define KERNEL_FONT_NB_CHAR_X ((KERNEL_FONT_BITMAP_WIDTH / KERNEL_FONT_BITMAP_CWIDTH) + 1)
#define KERNEL_FONT_NB_CHAR_Y ((KERNEL_FONT_BITMAP_HEIGHT / KERNEL_FONT_BITMAP_CHEIGHT) + 1)
// Define screen informations.
#define DISPLAY_SCREEN_WIDTH 128
#define DISPLAY_SCREEN_HEIGHT 64
// Primtives
extern void dclear(void);
extern void dprint(int x, int y, char const *str, ...);
extern void dascii(int x, int y, char const c);
extern void dscroll(int line);
extern void dupdate(void);
// Sheared Video RAM
extern uint32_t *VRAM;
#endif /*__LIB_DISPLAY_H__*/

12
include/lib/stdio.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef __LIB_STDIO_H__
# define __LIB_STDIO_H__
#include <stddef.h>
#include <stdint.h>
#include <stdarg.h>
/* vsprintf(), sprintf() - formatted output conversion. */
void vsprintf(char *str, char const *format, va_list ap);
void sprintf(char *str, char const *format, ...);
#endif /*__LIB_STDIO_H__*/

24
include/lib/string.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef __STRING_H__
# define __STRING_H__
#include <stdint.h>
#include <stddef.h>
/* memset() - fill memory with a constant byte. */
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
/* strcat() - concatenate two string */
char *strcat(char *dest, char const *src);
/* strcmp() - compare two strings */
int strcmp(const char *s1, const char *s2);
/* strcpy(), strncpy() - copy a string. */
char *strncpy(char *dest, char const *str, size_t size);
char *strcpy(char *dest, char const *src);
/* strlen - calculate the lenght of a string. */
size_t strlen(char const *str);
#endif /*__STRING_H__*/

View File

@ -1,46 +0,0 @@
#ifndef __STRING_H__
# define __STRING_H__
#include <types.h>
#include <stdarg.h>
// Define weak symbols
#define WEAK __attribute__((weak))
/* memset() - fill memory with a constant byte. */
WEAK void *memset(void *s, int c, size_t n);
#ifndef DEBUG
/* vsprintf(), sprintf() - formatted output conversion. */
void vsprintf(char *str, char const *format, va_list ap);
void sprintf(char *str, char const *format, ...);
#endif /* DEBUG */
/* strcat() - concatenate two string */
WEAK char *strcat(char *dest, char const *src);
/* strcmp() - compare two strings */
WEAK int strcmp(const char *s1, const char *s2);
/* strcpy(), strncpy() - copy a string. */
WEAK char *strncpy(char *dest, char const *str, size_t size);
WEAK char *strcpy(char *dest, char const *src);
/* strlen - calculate the lenght of a string. */
WEAK size_t strlen(char const *str);
//
// Custom string function.
//
/* strtotab() - generate table of word and indicate the number of word. */
int strtotab(int *argc, char ***argv, char const *str);
/* strtotab_quit() - free all allocated memory by strtotab function. */
void strtotab_quit(int *argc, char ***argv);
/* atoi_base() - atoi wrapped function, but add the base number. */
uint32_t atoi_base(char const *str, int base);
#endif /*__STRING_H__*/

View File

@ -1,56 +0,0 @@
#include <stdint.h>
#include <stddef.h>
extern int main(void);
//defined by bootstrap.ld
extern uint32_t bbss;
extern uint32_t sbss;
extern uint32_t bdata_rom;
extern uint32_t bdata_ram;
extern uint32_t sdata;
//
// section_dump()
// copy a memory region using symbol information.
//
__attribute__((section(".pretext")))
void section_dump(uint32_t * restrict dest, uint32_t * restrict load, size_t size)
{
size_t i;
i = -1;
while (++i < size >> 2)
dest[i] = load[i];
}
//
// section_reset()
// clear a memory region using symbol information.
//
__attribute__((section(".pretext")))
void section_reset(uint32_t *bsection, size_t size)
{
size_t i;
i = -1;
while (++i < size >> 2)
bsection[i] = 0;
}
//
// initialize() - the real add-in entry.
// We are currently running in the storage memory, so we should
// load data in RAM and wipe the bss section for initialize static
// and global variables.
//
__attribute__((section(".pretext.entry")))
int initialize(void)
{
int exit;
section_reset(&bbss, (size_t)&sbss);
section_dump(&bdata_ram, &bdata_rom, (size_t)&sdata);
exit = main();
return (exit);
}

View File

@ -1,30 +0,0 @@
#include <command.h>
#include <string.h>
// External symbols defined by the linker script.
extern uint32_t bcmd_cache;
extern uint32_t ecmd_cache;
//
// cmd_cache_find()
// Try to find the command into the command cache.
//
// NOTE:
// The cache is generated during the compilation; all command
// blocks is stored in the ".cmd.cache" section.
// We use the section symbols to know where the cache end.
// (see bootstrap.ld).
//
const struct cmd_block *cmd_cache_find(char const *name)
{
const struct cmd_block *cache;
size_t i;
i = -1;
cache = (void *)&bcmd_cache;
while ((ptrdiff_t)(&cache[++i]) != (ptrdiff_t)&ecmd_cache
&& strcmp(cache[i].name, name));
if ((ptrdiff_t)(&cache[i]) == (ptrdiff_t)&ecmd_cache)
return (NULL);
return (&cache[i]);
}

View File

@ -1,57 +0,0 @@
#include <command.h>
#include <string.h>
#include <errno.h>
//
// command_find
// Try to find the user command in the internal cache and execute
// the command's function.
//
static int command_find(int argc, char **argv, struct session_s *session,
struct vhex_s *vhex)
{
const struct cmd_block *command;
int tmp;
command = cmd_cache_find(*argv);
if (command == NULL)
return (EINVAL);
if (command->constructor == NULL){
strcpy(vhex->info, "function error");
return (ENOSYS);
}
tmp = session->anchor;
memset(vhex->info, '\0', CMD_LENGHT_MAX);
command->constructor(argc, argv, session, vhex->info);
if (*vhex->info == '\0')
sprintf(vhex->info, "%#x", session->anchor);
if (tmp != session->anchor)
session->cursor = 0;
return (0);
}
//
// command_entry()
// The goal of this part is to parse and execute the user's command.
//
void command_entry(struct session_s *session, struct vhex_s *vhex)
{
char **argv;
int argc;
int ret;
if (history_update(&vhex->history.list, vhex->insert.cmd) == 0){
vhex->history.offset = 0;
vhex->history.deep += 1;
}
ret = strtotab(&argc, &argv, vhex->insert.cmd);
memset(vhex->insert.cmd, '\0', CMD_LENGHT_MAX);
if (ret != 0){
sprintf(vhex->info, "error (%d)", ret);
return;
}
if (command_find(argc, argv, session, vhex) != 0)
strcat(vhex->info, "command error");
session->mode = (session->anchor == 0x00000000) ? UNUSED : NORMAL;
strtotab_quit(&argc, &argv);
}

View File

@ -1,228 +0,0 @@
#include <command.h>
#include <syscalls.h>
#include <string.h>
#include <errno.h>
// Internal prototype.
static void help(int argc, char **argv, struct session_s *session, char *info);
// Define help command into the cache section.
CMDBLOCK("help", &help,
"Help for Vhex version 1.0\n"
"This chapter introduces\noperations available with vhex.\n"
"\n"
"I] Keys mapping\n"
"II] Status bar\n"
"III] Unused mode\n"
"IV] Command mode\n"
"V] Normal mode\n"
"VI] Credits\n"
"VII] Copyright\n"
"\n"
"================================"
"I] Keys mapping\n"
"Move around: [UP], [DOWN]\n"
"Change mode: [OPTN]\n"
"Letter: [ALPHA] + [A ~ Z]\n"
"Letter lock: [SHIFT] + [ALPHA]\n"
"Letter unlock: [ALPHA]\n"
"Number: [0 ~ 9]\n"
"sessions: [F0 ~ F9]\n"
"\n"
"================================"
"II] Status bar\n"
"The first information (at the\nbottom left) display is the\nkeyboard status:\n"
" * [s] : shift mode.\n"
" * [l] : letter mode.\n"
" * [L] : caps lock.\n"
" * [n] : number mode.\n"
"The second information is the\ncommand zone.\n"
"The third information is the\ncurrent mode (unused, normal,\ncommand).\n"
"And the last information is the session's id currently using.\n"
"\n"
"================================"
"III] Unused mode\n"
"This mode is set when the\nsession is not used.\n"
"Basically you can't do a lot of things, but you can enter into\n"
"the command mode using the\n[OPTN] key.\n"
"\n"
"================================"
"IV] Normal mode.\n"
"This mode allows the user to\nmove into the Virtual Memory\n"
"using [UP] and [DOWN].\n"
"Be careful, there is no security"
"and some parts of the Virtual\n"
"Memory can make your\ncalculator crash.\n"
"If a crash occurs, don't worry, you have \"just\" read a\n"
"non-readable space.\n"
"Your machine will continue to\nwork perfectly after\nthe reset.\n"
"\n"
"================================"
"V] Command mode\n"
"The command mode is probably\nthe most important part\nof Vhex.\n"
"It's the only way to move\nquickly into the different part\n"
"of the Virtual Memory.\n"
"To enter in command mode the\nuser can press the [OTPN] key,\n"
"normally a \":#\" appear and\nthe user can write\ncommand.\n"
"All commands currently\nintegrated in Vhex:\n"
" :systab\n"
" :vbrjmp <zone>\n"
" :syscall <id>\n"
" :ram <zone>\n"
" :rom\n"
" :help <command>\n"
"We invited you to try\n\":help <cmd>\" if you don't know how a"
" command work.\n"
"Each command typed by the user\nis stored in a history that it\n"
"can access using [UP] and\n[DOWN] keys.\n"
"\n"
"================================"
"VI] Credits\n"
"Special thank to:\n"
" - Lephenixnoir\n"
" - PierrotLL\n"
" - Simon Lothar\n"
" - Kristaba\n"
"And all communities of Planet\nCasio for his help.\n"
"specially to LephenixNoir for\nhis advices and his patience.\n"
"\n"
"================================"
"VII] Copyright\n"
"The Vhex programme use CC0\nlicence.\n"
"It allows anyone to freely\nreuse, improve or modify my\n"
"work for any purpose and\nwithout any legal restrictions, "
"except those required by law.\n");
/* get_nb_line() - Return the number of lines contain in the command's manual. */
static int get_nb_line(char const *str)
{
int nb_line;
int cursor;
if (str == NULL || *str == '\0')
return (-EBADMSG);
cursor = 0;
nb_line = 0;
do {
cursor += 1;
if (cursor >= COLUMN_OFFSET || *str == '\n'){
nb_line += 1;
cursor = 0;
}
} while (*(++str) != '\0');
return (nb_line + 1);
}
/* get_line() - Return the address of a target line */
static const char *get_line(char const *str, int line)
{
int cursor;
int nb_line;
if (line == 0)
return (str);
cursor = 0;
nb_line = 0;
do {
cursor += 1;
if (cursor >= COLUMN_OFFSET || *str == '\n'){
nb_line += 1;
cursor = 0;
}
} while (*(++str) != '\0' && nb_line < line);
return (str);
}
//
// display_text() - Display only lines which should be visible.
//
// NOTE:
// Due to the Casio's GetKey function, the font used is a little bit weird,
// some characters have not the same size, so we can't calculate easily
// the line size. (TODO: fix that).
//
static void display_text(char *buf, char const *str, int current_line)
{
char const *text;
int nb_line;
int cursor;
text = get_line(str, current_line);
if (*text == '\0')
return;
nb_line = 0;
cursor = 0;
do {
if (*text != '\n'){
buf[cursor] = *text;
cursor += 1;
}
if (cursor >= COLUMN_OFFSET || *text == '\n'){
buf[cursor] = '\0';
print(0, nb_line * FONT_HEIGHT, buf);
nb_line += 1;
cursor = 0;
continue;
}
} while (*(++text) != '\0' && nb_line < LINE_OFFSET);
if (cursor != 0)
print(0, nb_line * FONT_HEIGHT, buf);
}
/* help_engine() - Display help information and handle keyboard. */
static void help_engine(char const *text, int nb_line)
{
char buf[COLUMN_OFFSET + 1];
unsigned int key;
int cursor;
int exit;
exit = 1;
cursor = 0;
while (exit != 0){
dclear();
// Display text.
display_text(buf, text, cursor);
// Display exit info.
dclear_area(0, SCREEN_HEIGHT - FONT_HEIGHT - 2, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
dline_horizontal(SCREEN_HEIGHT - FONT_HEIGHT - 2, 0, SCREEN_WIDTH - 1);
print(0, SCREEN_HEIGHT - FONT_HEIGHT, "press [EXIT]");
sprintf(buf, "%d/%d", cursor + 1, nb_line + 1);
print(SCREEN_WIDTH - (strlen(buf) * FONT_WIDTH) - 1, SCREEN_HEIGHT - FONT_HEIGHT, buf);
getkey(&key);
// Keys hanlding.
if (key == KEY_UP && cursor > 0)
cursor -= 1;
if (key == KEY_DOWN && cursor < nb_line)
cursor += 1;
if (key == KEY_EXIT)
exit = 0;
}
}
/* help() - display command manual pages. */
static void help(int argc, char **argv, struct session_s *session, char *info)
{
const struct cmd_block *command;
int nb_line;
(void)session;
command = cmd_cache_find((argc == 1) ? "help" : argv[1]);
if (command == NULL){
strcpy(info, "command error");
return;
}
nb_line = 0;
if (command->man != NULL)
nb_line = get_nb_line(command->man);
if (command->man == NULL || nb_line < 0){
strcpy(info, "no help entry");
return;
}
nb_line -= LINE_OFFSET + 1;
if (nb_line < 0)
nb_line = 0;
help_engine(command->man, nb_line);
}

View File

@ -1,65 +0,0 @@
#include <command.h>
#include <string.h>
// Internal prototype.
static void address_jump(int argc, char **argv, struct session_s *session, char *info);
// Define the command block into the cache.
CMDBLOCK("jmp", &address_jump,
"JMP command help\n"
"This command takes one\nparameter: the address (hexa)\n"
"you would jump into the Virtual Memory.\n"
"\n"
"Be careful, there is no security"
"and some parts of the Virtual\n"
"Memory can make your\ncalculator crash.\n"
"\n"
"If a crash occurs, don't worry, you have \"just\" read a\n"
"non-readable space.\n"
"Your calculator will continue\nto work perfectly after\nthe reset.\n"
"\n"
"Virtual Memory map:\n"
"Area P0 - 2Go - MMU enable\n"
"0x00300000 : add-in header\n"
"0x00300200 : add-in mapping\n"
"0x08000000 : RAM (cache)\n"
"Area P1 - 500Mo - MMU disable\n"
"0x80000000 : ROM (cache)\n"
"0x88000000 : RAM (cache)\n"
"Area P2 - 500Mo - MMU disable\n"
"0xa0000000 : ROM (no cache)\n"
"0xa8000000 : RAM (no cache)\n"
"Area P3 - 500Mo - MMU enable\n"
"?????? CRASH ??????\n"
"Area P4 - 500Mo - MMU disable\n"
"0xe0000000 : Store queue area\n"
"0xe5000000 : On chip RAM\n"
"0xf0000000 : Instr. cache addr\n"
"0xf1000000 : Instr. cache data\n"
"0xf2000000 : Instr. TLB addr\n"
"0xf3000000 : Instr. TLB data\n"
"0xf4000000 : Operand cache addr\n"
"0xf5000000 : Operand cache data\n"
"0xf6000000 : TLB/PMB cache addr\n"
"0xf7000000 : TLB/PMB cache data\n"
"0xfc000000 : Control register\n"
);
static INLINE int check_address(char *str)
{
--str;
while ((*(++str) >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f'));
return ((*str != '\0') ? 1 : 0);
}
/* address_jump() - jump into Virtual Memory. */
static void address_jump(int argc, char **argv, struct session_s *session, char *info)
{
if (argc != 2 || check_address(argv[1]) != 0){
strcpy(info, "arguments error");
return;
}
// clear the lower bits to force align the address.
// (one instruction takes 2 bytes, so we need to respect the alignment).
session->anchor = atoi_base(argv[1], 16) >> 1 << 1;
}

View File

@ -1,51 +0,0 @@
#include <command.h>
#include <string.h>
// Internal prototype.
static void ram_jump(int argc, char **argv, struct session_s *session, char *info);
/* Define the command block into the cache section. */
CMDBLOCK("ram", &ram_jump,
"RAM command help\n"
"This function allows user to\njump into different parts of\n"
"the RAM mapped in the Virtual\nMemory.\n"
"\n"
":ram p0\n"
"Jump into the P0 area, basically"
"the user space who is managed\n"
"by the Memory Management\nUnit.\n"
"\n"
":ram p1\n"
"Jump into the RAM mapped in the P1 area; MMU is disabled and\n"
"the area is cached.\n"
"\n"
":ram p2\n"
"Jump into the RAM mapped in the P2 area; MMU is disable "
"and the area is not cached.\n"
"\n"
":ram p4\n"
"Jump into the internal chip\nmemory area; MMU is enabled\n"
"and the area is cached.\n"
);
/* ram_jump() - jump into the RAM mapped in different parts of the Virtual Memory. */
static void ram_jump(int argc, char **argv, struct session_s *session, char *info)
{
if (argc != 2){
strcpy(info, "argument error");
return;
}
if (strcmp(argv[1], "p0") && strcmp(argv[1], "p1")
&& strcmp(argv[1], "p2") && strcmp(argv[1], "p4")){
sprintf(info, "bad argument");
return;
}
if (!strcmp(argv[1], "p0"))
session->anchor = 0x08100000;
if (!strcmp(argv[1], "p1"))
session->anchor = 0x88000000;
if (!strcmp(argv[1], "p2"))
session->anchor = 0xa8000000;
if (!strcmp(argv[1], "p4"))
session->anchor = 0xe5000000;
}

View File

@ -1,44 +0,0 @@
#include <command.h>
#include <string.h>
// internal prototype.
static void rom_jump(int argc, char **argv, struct session_s *session, char *info);
// Define the command into the cache.
CMDBLOCK("rom", &rom_jump,
"ROM command help\n"
"This command allows user to\njump into different parts of\n"
"the ROM mapped in the Virtual\nMemory.\n"
"\n"
":rom addin\n"
"Jump into the dynamic add-in\nmapping area.\n"
"Normaly you can see the\nVhex binary :)\n"
"(see \":help jmp\" to get the\nVirtual Memory map)\n"
"\n"
":rom p1\n"
"Jump into the ROM mapped in\nthe P1 area.\n"
"MMU is disable and the area\nis cached.\n"
"\n"
"rom p2\n"
"Jump into the ROM mapped in\nthe P2 area.\n"
"MMU is disable and the area\nis not cached.\n"
);
/* rom_jump() - jump into the ROM mapped in different parts of the Virtual Memory. */
static void rom_jump(int argc, char **argv, struct session_s *session, char *info)
{
if (argc != 2){
strcpy(info, "argument error");
return;
}
if (strcmp(argv[1], "addin") && strcmp(argv[1], "p1") && strcmp(argv[1], "p2")){
sprintf(info, "bad argument");
return;
}
if (!strcmp(argv[1], "addin"))
session->anchor = 0x00300200;
if (!strcmp(argv[1], "p1"))
session->anchor = 0x80000000;
if (!strcmp(argv[1], "p2"))
session->anchor = 0xa0000000;
}

View File

@ -1,120 +0,0 @@
#include <command.h>
#include <string.h>
// Internal prototype.
static void syscall_jump(int argc, char **argv, struct session_s *session, char *info);
/* Define command block into the cache section. */
CMDBLOCK("syscall", &syscall_jump,
"SYSCALL command help\n"
"Take one parameter: syscall id.\n"
"This command will jump at the\nsyscall's code entry.\n"
"\n"
"Syscall list (not exhaustive):\n"
"0x013 : GLibAddinAppExecutionCheck\n"
"0x014 : GLibGetAddinLibInfo\n"
"0x014 : GLibGetOSVersionInfo\n"
"0x01c : Bdisp_WriteGraph_VRAM\n"
"0x01d : Bdisp_WriteGraph_DD\n"
"0x01e : Bdisp_WriteGraph_DDVRAM\n"
"0x022 : Bdisp_ReadArea_VRAM\n"
"0x023 : Bdisp_ReadArea_DD_OS\n"
"0x024 : Bdisp_GetDisp_DD\n"
"0x026 : DD_GET\n"
"0x028 : Bdisp_PutDisp_DD\n"
"0x030 : Bdisp_DrawLineVRAM\n"
"0x031 : Bdisp_ClearLine_VRAM\n"
"0x118 : Bcre_cychdr\n"
"0x119 : Bdel_cychdr\n"
"0x142 : Bdisp_AllClr_DD\n"
"0x143 : Bdisp_AllClr_VRAM\n"
"0x144 : Bdisp_AllClr_DDVRAM\n"
"0x145 : Bdisp_GetDisp_VRAM\n"
"0x147 : Bdisp_SetPoint_DD\n"
"0x148 : Bdisp_SetPoint_DDVRAM\n"
"0x149 : Bdisp_GetPoint_VRAM\n"
"0x14a : Bdisp_AreaClr_DD\n"
"0x14b : Bdisp_AreaClr_VRAM\n"
"0x14c : Bdisp_AreaClr_DDVRAM\n"
"0x14d : Bdisp_AreaReverseVRAM\n"
"0x11a : Bsta_cychdr\n"
"0x11b : Bstp_cychdr\n"
"0x11f : Bdisp_PutDispArea_DD\n"
"0x1e7 : BfileFLS_CloseFile\n"
"0x218 : flsFindCLose\n"
"0x242 : Bkey_Set_RepeatTime\n"
"0x243 : Bkey_Get_RepeatTime\n"
"0x244 : Bkey_Set_RepeatTime_Default\n"
"0x247 : Bkey_GetKeyWait\n"
"0x24c : Chattering\n"
"0x374 : BMCSRenameVariable\n"
"0x3ed : SetFlagPaturn\n"
"0x3fa : Hmem_SetMMU\n"
"0x420 : BSrl_DummyWAIT\n"
"0x42c : Bfile_OpenFile_OS\n"
"0x42d : Bfile_CloseFile_OS\n"
"0x42e : Bfile_GetMediaFree_OS\n"
"0x42f : Bfile_GetFileSize_OS\n"
"0x431 : Bfile_SeekFile_OS\n"
"0x432 : Bfile_ReadFile_OS\n"
"0x434 : Bfile_CreateEntry\n"
"0x435 : Bfile_WriteFile_OS\n"
"0x439 : Bfile_DeleteEntry\n"
"0x43b : Bfile_FindFirst\n"
"0x43d : Bfile_FindClose\n"
"0x43c : Bfile_FindNext\n"
"0x462 : GetAppName\n"
"0x494 : CallBackAtQuitMainFunction\n"
"0x807 : Locate_OS\n"
"0x82b : MCSPutVar2\n"
"0x830 : MCSOvwDat2\n"
"0x836 : MCSDelVar2\n"
"0x840 : MCSGetDlen2\n"
"0x841 : MCSGetData1\n"
"0x844 : MCSGetCapa\n"
"0x8fe : PopUpWin\n"
"0x808 : Print\n"
"0x809 : PrintRev\n"
"0x80b : PrintRev\n"
"0x80d : PrintRLine\n"
"0x80a : PrintC\n"
"0x80c : PrintLine\n"
"0x813 : SaveDisp\n"
"0x814 : RestoreDisp\n"
"0x90f : GetKey\n"
"0x9ad : PrintXY\n"
"0xacc : free\n"
"0xacd : malloc\n"
"0xc4f : PrintMiniSd\n"
"0xe6b : calloc\n"
"0xe6d : realloc\n"
"0x1032 : Bkey_GetKeyTableInfo\nJumpFunc\n"
);
static INLINE int check_address(char *str)
{
--str;
while ((*(++str) >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f'));
return ((*str != '\0') ? 1 : 0);
}
//
// syscall_jump()
// Casio doesn't use the TRAPA instruction (software interruption), for switch from
// user mode to privileged mode. They just jump always at 0x80010070 and use the
// table of syscall addresses to redirect the jump. (and the table address is always
// stored at 0x8001007c).
//
static void syscall_jump(int argc, char **argv, struct session_s *session, char *info)
{
uint32_t *systab;
uint32_t id;
if (argc != 2 || check_address(argv[1]) != 0){
strcpy(info, "arguments error");
return;
}
id = atoi_base(argv[1], 16);
systab = (void*)(*(uint32_t *)0x8001007c);
session->anchor = systab[id];
}

View File

@ -1,29 +0,0 @@
#include <command.h>
#include <string.h>
// Internal prototype.
static void systab_jump(int argc, char **argv, struct session_s *session, char *info);
// Define the command block into the cache
CMDBLOCK("systab", &systab_jump,
"SYSTAB command help\n"
"This function allows user to\njump into the Casio \"syscall\n"
"handler\".\n"
"\n"
"Curiously, Casio doesn't use the"
"TRAPA instruction for handle\n"
"syscall, but jump at\n0x80010070.\n"
"This don't explain why we are\nalways in privileged mode, but\n"
"now we can affirm that Casio\ndo it intentionally.\n"
);
/* systab_jump() - Jump into the Casio "syscall handler". */
static void systab_jump(int argc, char **argv, struct session_s *session, char *info)
{
if (argc != 1){
strcpy(info, "argument error");
return;
}
(void)argv;
session->anchor = 0x80010070;
}

View File

@ -1,49 +0,0 @@
#include <command.h>
#include <string.h>
// Internal prototype
static void vbrjmp(int argc, char **argv, struct session_s *session, char *info);
// TODO: write doc.
CMDBLOCK("vbrjmp", &vbrjmp,
"VBR JUMP command help\n"
"This command jump into Casio's\nhandlers.\n"
"\n"
"Due to the SH3 / SH4 VBR system\n, there are 3 vectors offset\n"
"called by the processor:\n"
" * exception (VBR + 0x100)\n"
" * tlb miss (VBR + 0x400)\n"
" * interrupt (VBR + 0x600)\n"
"\n"
"You can access to each handler\nusing this command list:\n"
":vbrjmp except VBR + 0x100\n"
":vbrjmp fault VBR + 0x400\n"
":vbrjmp int VBR + 0x600\n"
);
//
// vbr_jump() - jump to the exception, tlb or interrupt, Casio handler.
// Due to the SH3 / SH4 VBR system, there are 3 vectors offset called
// by the processor:
// * vbr + 0x100 -> general exeptions.
// * vbr + 0x400 -> tlb miss.
// * vbr + 0x600 -> interrupts.
//
static void vbrjmp(int argc, char **argv, struct session_s *session, char *info)
{
if (argc != 2){
strcpy(info, "arguments error");
return;
}
if (strcmp(argv[1], "fault") && strcmp(argv[1], "except") && strcmp(argv[1], "int")){
sprintf(info, "bad argument");
return;
}
__asm__ volatile ("stc vbr, %0" : "=r"(session->anchor));
if (!strcmp(argv[1], "except"))
session->anchor += 0x100;
if (!strcmp(argv[1], "fault"))
session->anchor += 0x400;
if (!strcmp(argv[1], "int"))
session->anchor += 0x600;
}

View File

@ -1,18 +0,0 @@
#include <command.h>
#include <string.h>
// internal prototype.
static void quit(int argc, char **argv, struct session_s *session, char *info);
// Define the command into the cache.
CMDBLOCK("quit", &quit, NULL);
/* quit() - switch to UNUSED mode */
static void quit(int argc, char **argv, struct session_s *session, char *info)
{
(void)argc;
(void)argv;
strcpy(info, "exit");
session->mode = UNUSED;
session->anchor = 0x00000000;
}

View File

@ -1,16 +0,0 @@
#include <command.h>
#include <string.h>
// internal prototype.
static void where(int argc, char **argv, struct session_s *session, char *info);
// Define the command into the cache.
CMDBLOCK("where", &where, NULL);
/* where() - display the user positision in the Virtual Memory. */
static void where(int argc, char **argv, struct session_s *session, char *info)
{
(void)argc;
(void)argv;
sprintf(info, "%#x", session->anchor + (session->cursor << 1));
}

View File

@ -1,72 +0,0 @@
#include <utils.h>
#include <syscalls.h>
#include <opcode.h>
#include <string.h>
//TODO: move me ?
static INLINE int get_shift(uint16_t mask)
{
int i;
if (mask == 0x0000)
return (0);
i = -1;
while (++i < 16 && !(mask & (0x01 << i)));
return (i);
}
/* get_instructions() - find mnemonic and instruction argument(s) */
static void get_instructions(char *str, uint16_t bytes_code)
{
int shift[ARGUMENTS_MAX];
size_t i;
size_t j;
i = -1;
while (opcode[++i].name != NULL
&& (bytes_code & opcode[i].mask) != opcode[i].code);
if (opcode[i].name == NULL){
strcpy(str, "????");
return;
}
j = -1;
while (++j < ARGUMENTS_MAX)
shift[j] = get_shift(opcode[i].arg_mask[j]);
//TODO: update this.
sprintf(str, opcode[i].name,
(bytes_code & opcode[i].arg_mask[0]) >> shift[0],
(bytes_code & opcode[i].arg_mask[1]) >> shift[1],
(bytes_code & opcode[i].arg_mask[2]) >> shift[2]);
}
//
// display_instructions()
// Translate "on-the-fly" each binary instructions stored at
// the anchor location.
// Almost instructions can be translated; only FPU instructions
// is not handled because it's not available on the SH3 based MPU.
//
void display_instructions(const struct session_s *session)
{
char mnemonic[128];
uint16_t *area;
char buf[64];
size_t y;
if (session->mode == COMMAND){
restore_window(1);
return;
}
if (session->mode == UNUSED || session->anchor == 0x00000000){
print((SCREEN_WIDTH >> 1) - ((sizeof("Empty session") * FONT_WIDTH) >> 1),
(SCREEN_HEIGHT >> 1) - (FONT_HEIGHT >> 1), "Empty session");
return;
}
y = -1;
area = (void*)(session->anchor + (session->cursor << 1));
while (++y < LINE_OFFSET){
get_instructions(mnemonic, area[y]);
sprintf(buf, "%4x %4x %s", &(area[y]), area[y], mnemonic);
print(0, y * FONT_HEIGHT, buf);
}
}

View File

@ -1,27 +0,0 @@
#include <utils.h>
#include <syscalls.h>
#include <string.h>
/* display_metainfo() - display the "status" bar and display user's information */
void display_metainfos(const struct vhex_s *vhex, const struct session_s *session)
{
static const char *mode_name[] = {"unused", "command", "normal", "free"};
static const char insert_name[] = {'l', 'L', 'n', 's'};
const void *tmp;
char buf[32];
// clear area
dclear_area(0, SCREEN_HEIGHT - FONT_HEIGHT - 2, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
dline_horizontal(SCREEN_HEIGHT - FONT_HEIGHT - 2, 0, SCREEN_WIDTH - 1);
// Display informations
sprintf(buf, "[%s][%d]", mode_name[session->mode], vhex->current_session);
print(SCREEN_WIDTH - (strlen(buf) * FONT_WIDTH) - 1, SCREEN_HEIGHT - FONT_HEIGHT, buf);
if (session->mode == COMMAND)
sprintf(buf, "[%c]:%s#", insert_name[vhex->insert.mode], vhex->insert.cmd);
else {
tmp = (*vhex->info == '\0') ? vhex->insert.cmd : vhex->info;
sprintf(buf, "[%c] %s", insert_name[vhex->insert.mode], tmp);
}
print(0, SCREEN_HEIGHT - FONT_HEIGHT, buf);
}

View File

@ -1,64 +0,0 @@
#ifndef DEBUG
# include <history.h>
# include <syscalls.h>
#else
# include "history.h"
# include <stdlib.h>
#endif
#include <string.h>
#include <errno.h>
//---
// history_update()
// Add new history node to the chained list. This is a singly
// linked list, but the node insertion from the beginning.
//
// Exemple: add node A, B, C and D
// 1. A -> NULL
// 2. B -> A -> NULL
// 3. C -> B -> A -> NULL
// 4. D -> C -> B -> A -> NULL
//---
int history_update(struct node **list, const char *data)
{
void *swap;
if (list == NULL)
return (EFAULT);
swap = *list;
*list = (struct node *)malloc(sizeof(struct node));
if (*list == NULL){
*list = swap;
return (ENOMEM);
}
strcpy((void*)(*list)->data, data);
(*list)->next = swap;
return (0);
}
//
// history_get()
// primitive function which will return the data stored in
// the "offset" position in the list.
//
const void *history_get(struct node *list, off_t offset)
{
if (list == NULL)
return (NULL);
if (offset == 0)
return (list->data);
return (history_get(list->next, offset - 1));
}
//
// history_quit()
// Free all allocated memory.
//
void history_quit(struct node **list)
{
if (list == NULL || *list == NULL)
return;
history_quit(&(*list)->next);
free(*list);
*list = NULL;
}

View File

@ -0,0 +1,59 @@
#include <kernel/context.h>
#include <kernel/hardware/keysc.h>
#include <kernel/hardware/intc.h>
void fx9860_context_save(fx9860_context_t *context)
{
// Save Interrupt Controller (INTC)
context->intc.ipra = SH7305_INTC.IPRA.WORD;
context->intc.iprb = SH7305_INTC.IPRB.WORD;
context->intc.iprc = SH7305_INTC.IPRC.WORD;
context->intc.iprd = SH7305_INTC.IPRD.WORD;
context->intc.ipre = SH7305_INTC.IPRE.WORD;
context->intc.iprf = SH7305_INTC.IPRF.WORD;
context->intc.iprg = SH7305_INTC.IPRG.WORD;
context->intc.iprh = SH7305_INTC.IPRH.WORD;
context->intc.ipri = SH7305_INTC.IPRI.WORD;
context->intc.iprj = SH7305_INTC.IPRJ.WORD;
context->intc.iprk = SH7305_INTC.IPRK.WORD;
context->intc.iprl = SH7305_INTC.IPRL.WORD;
// Save Key Scan (KEYSC) context.
context->keyboard.control = SH7305_KEYSC.CONTROL.WORD;
context->keyboard.autofix = SH7305_KEYSC.AUTOFIX.WORD;
context->keyboard.scan_mode = SH7305_KEYSC.SCAN_MODE.WORD;
context->keyboard.scan_state = SH7305_KEYSC.SCAN_STATE.WORD;
context->keyboard.interrupt = SH7305_KEYSC.INTERRUPT.WORD;
context->keyboard.scan_wait = SH7305_KEYSC.SCAN_WAIT.WORD;
context->keyboard.scan_interval = SH7305_KEYSC.SCAN_INTERVAL;
context->keyboard.kyoutdr = SH7305_KEYSC.KYOUTDR.WORD;
context->keyboard.kyindr = SH7305_KEYSC.KYINDR.WORD;
}
void fx9860_context_restore(fx9860_context_t *context)
{
// Restore Key Scan (KEYSC) context.
SH7305_KEYSC.CONTROL.WORD = context->keyboard.control;
SH7305_KEYSC.AUTOFIX.WORD = context->keyboard.autofix;
SH7305_KEYSC.SCAN_MODE.WORD = context->keyboard.scan_mode;
SH7305_KEYSC.SCAN_STATE.WORD = context->keyboard.scan_state;
SH7305_KEYSC.INTERRUPT.WORD = context->keyboard.interrupt;
SH7305_KEYSC.SCAN_WAIT.WORD = context->keyboard.scan_wait;
SH7305_KEYSC.SCAN_INTERVAL = context->keyboard.scan_interval;
SH7305_KEYSC.KYOUTDR.WORD = context->keyboard.kyoutdr;
SH7305_KEYSC.KYINDR.WORD = context->keyboard.kyindr;
// Restore Interrupt Controller (INTC)
SH7305_INTC.IPRA.WORD = context->intc.ipra;
SH7305_INTC.IPRB.WORD = context->intc.iprb;
SH7305_INTC.IPRC.WORD = context->intc.iprc;
SH7305_INTC.IPRD.WORD = context->intc.iprd;
SH7305_INTC.IPRE.WORD = context->intc.ipre;
SH7305_INTC.IPRF.WORD = context->intc.iprf;
SH7305_INTC.IPRG.WORD = context->intc.iprg;
SH7305_INTC.IPRH.WORD = context->intc.iprh;
SH7305_INTC.IPRI.WORD = context->intc.ipri;
SH7305_INTC.IPRJ.WORD = context->intc.iprj;
SH7305_INTC.IPRK.WORD = context->intc.iprk;
SH7305_INTC.IPRL.WORD = context->intc.iprl;
}

View File

@ -0,0 +1,64 @@
#include <kernel/types.h>
/* check_sh3 - Detecting sh3-based MPU */
static mpu_t check_sh3(uint16_t tplcr)
{
if (tplcr == 0x0fff)
return (MPU_SH7337);
if (tplcr == 0x00ff)
return (MPU_SH7355);
return (MPU_UNKNOWN);
}
/* check_sh3 - Detecting sh4-based MPU */
static mpu_t check_sh4(void)
{
volatile uint32_t *pvr = (void *)0xff000030;
volatile uint32_t *prr = (void *)0xff000044;
uint32_t product;
if ((*pvr & 0xffffff00) != 0x10300b00)
return (MPU_UNKNOWN);
product = *prr & 0xfffffff0;
if (product == 0x00002c00)
return (MPU_SH7305);
if (product == 0x00002200)
return (MPU_SH7724);
return (MPU_UNKNOWN);
}
//
// get_mpu()
//
// Return the MPU identifier of the calculator.
// Thanks to SimonLothar and Lephenixnoir for this function
// and related information.
//
// Processor version register (PVR) and product control register (PRR)
// hold information about the MPU version, they but are only accessible on
// SH-4-based MPUs.
// To detect SH-3-based MPUs, this function uses port L control register
// (PLCR), whose bits 8 to 15 cannot be set with SH7337 where bits 8 to 11
// can be set with SH7355.
//
// Additionally, the CPU core ID register (CPIDR) at 0xff000048 returns 1
// on SH7305.
//
mpu_t mpu_get(void)
{
volatile uint16_t *plcr = (void *)0xa4000114;
uint16_t splcr;
uint16_t tplcr;
mpu_t mpu;
// Check port L control register.
splcr = *plcr;
*plcr = 0xffff;
tplcr = *plcr;
*plcr = splcr;
mpu = check_sh3(tplcr);
if (mpu != MPU_UNKNOWN)
return (mpu);
return (check_sh4());
}

View File

@ -0,0 +1,49 @@
.globl _section_wipe
.global _section_load
.type _section_load, @function
.type _section_wipe, @function
.align 2
/*
** section_map(uint32_t *dest, uint32_t *src, size_t size)
** Load section using his symbols.
*/
_section_load:
shlr2 r6 ! sections are force 4-aligned by the linker.
tst r6, r6 ! check null section...
bt load_loop_end ! ...if null, exit.
load_loop_entry:
mov.l @r5, r1 ! get "src" data.
mov.l r1, @r4 ! copy into the "dest" section.
add #4, r5 ! update "src" address.
dt r6 ! check the load size.
bf/s load_loop_entry ! loop jump.
add #4, r4 ! update "dest" address.
load_loop_end:
rts ! clean exit.
nop ! delayed branch.
/*
** section_wipe(uint32_t *bsection, size_t size)
** Wipe section using his symbols.
*/
_section_wipe:
mov #0, r0 ! wipe data.
shlr2 r5 ! the section force 4-aligned by the linker.
tst r5, r5 ! Check null section...
bt wipe_loop_end ! ...if null, exit !
wipe_loop_entry:
mov.l r0, @r4 ! wipe section part.
dt r5 ! check the section size.
bf/s wipe_loop_entry ! loop jump.
add #4, r4 ! address update.
wipe_loop_end:
rts ! clean exit.
nop ! delayed branch.
.end

View File

@ -0,0 +1,151 @@
#include <stdint.h>
#include <stddef.h>
#include <kernel/context.h>
#include <kernel/atomic.h>
#include <kernel/types.h>
#include <lib/display.h>
#include <lib/string.h>
// Internal symbols
//uint32_t gcc_fix[256];
//uint32_t *VRAM = gcc_fix;
mpu_t current_mpu = MPU_UNKNOWN;
const char *casio_os_version = (void*)0xa0010020;
fx9860_context_t casio_context;
uint32_t casio_vbr;
// Symbols defined by the linker
extern uint32_t bbss;
extern uint32_t sbss;
extern uint32_t bdata_ram;
extern uint32_t bdata_rom;
extern uint32_t sdata;
extern uint32_t bvhex_ram;
extern uint32_t bvhex_rom;
extern uint32_t svhex;
extern uint32_t vhex_vbr;
// Internal functions.
extern void section_wipe(uint32_t *section, size_t size);
extern void section_load(uint32_t *dest, uint32_t *src, size_t size);
extern uint32_t vbr_set(uint32_t new_vbr);
extern uint32_t vbr_get(void);
extern mpu_t mpu_get(void);
extern int main(void);
extern void vhex_context_set(void);
__attribute__((section(".pretext")))
int start(void)
{
int error;
// Wipe .bss section and dump .data / Vhex sections
section_wipe(&bbss, (size_t)&sbss);
section_load(&bdata_ram, &bdata_rom, (size_t)&sdata);
section_load(&bvhex_ram, &bvhex_rom, (size_t)&svhex);
// Check MPU hardware.
current_mpu = mpu_get();
if (current_mpu != MPU_SH7305)
{
return (0);
}
// Mask interrupt, change context and switch VBR.
atomic_start();
fx9860_context_save(&casio_context);
casio_vbr = vbr_set((uint32_t)&vhex_vbr);
vhex_context_set();
atomic_end();
// VBR test.
__asm__ volatile ("trapa #0");
// Call high level abstraction.
error = main();
// Mask interrupt, change context and switch VBR.
atomic_start();
fx9860_context_restore(&casio_context);
vbr_set(casio_vbr);
atomic_end();
// Return the abstraction error.
return (error);
}
//
// initialize() - kernel entry
// This is the "real" entry of the kernel (after stack and CPU configuration).
// This part *SHOULD* be exception safe because the CPU block all exception and interruption,
// so if an exception occur during the "bootstrap" part, the processor will "crash".
//
/*void initialize(void)
{
interrupt_block();
printk(KERN_NOTICE, "Kernel initialization...\n");
// Wipe BSS section !
printk(KERN_NOTICE, "Wipe bss / dump data...\n");
memcpy(&bdata_ram, &bdata_rom, (size_t)&sdata);
memset(&bbss, 0x00, (size_t)&sbss);
// Check MPU.
current_mpu = mpu_get();
if (current_mpu != MPU_SH7305)
{
printk(KERN_NOTICE, "ARCH ERROR !\n");
int i = -1;
while (++i < 500000);
return (0);
}
// Dump kernel and data.
printk(KERN_NOTICE, "Dump VBR space...\n");
memcpy(&bvhex_ram, &bvhex_rom, (size_t)&svhex);
// Initialize Interruption (extern module, VBR, handlers)
printk(KERN_NOTICE, "Initialize hardware context...\n");
sh7305_context_initialize();
// Save / set new VBR.
printk(KERN_NOTICE, "Switch VBR / SR register...\n");
__asm__ volatile (
"stc vbr, %0;"
"stc sr, %1;"
"ldc %2, vbr;"
"ldc %3, sr"
: "=r"(casio_vbr), "=r"(casio_sr)
: "r"(&vhex_vbr), "r"(0x60000000)
:
);
printk(KERN_NOTICE, "Initialize heap space...\n");
pm_heap_initialize((void*)0x8806000, (void*)0x8808000, 32);
// Kernel initialized !
printk(KERN_NOTICE, "Kernel initialized !\n");
interrupt_unblock();
// Call shell.
shell_entry();
// Kernel exit part.
printk(KERN_NOTICE, "Kernel exit !");
interrupt_block();
// restore Casio's context.
printk(KERN_NOTICE, "Restore hardware context...\n");
sh7305_context_restore();
// Restore VBR / CPU configurations.
printk(KERN_NOTICE, "Restore VBR / SR...\n");
__asm__ volatile ("ldc %0, vbr" : : "r"(&casio_vbr) : );
__asm__ volatile ("ldc %0, sr" : : "r"(casio_sr) : );
// Clean exit.
interrupt_unblock();
return (0);
}*/

View File

@ -0,0 +1,35 @@
.global _vbr_get
.global _vbr_set
.type _vbr_set, @function
.type _vbr_get, @function
.text
.align 2
_vbr_get:
stc vbr, r0 ! Get VBR register.
rts ! Exit
nop ! (db) nop
_vbr_set:
! Block interrupt
stc sr, r1 ! Get SR register.
mov r1, r3 ! Save current SR data.
mov.l .bl_mask, r2 ! Get SR.BL mask.
or r2, r1 ! Set SR.BL to 1.
ldc r1, sr ! Update SR register.
! Get / Changle VBR
stc vbr, r0 ! Get VBR register.
ldc r4, vbr ! Update VBR register.
! Unblock interrupt.
ldc r3, sr ! Restore SR register.
! Exit
rts ! Exit
nop ! (db) nop
.align 4
.bl_mask: .long 0x100000f0
.end

View File

@ -0,0 +1,52 @@
#include <stdint.h>
#include <stddef.h>
#include <kernel/hardware/keysc.h>
#include <kernel/hardware/intc.h>
void vhex_context_set(void)
{
// Initialize Interrupt Controller (INTC).
SH7305_INTC.IPRA.WORD = 0x0000;
SH7305_INTC.IPRB.WORD = 0x0000;
SH7305_INTC.IPRC.WORD = 0x0000;
SH7305_INTC.IPRD.WORD = 0x0000;
SH7305_INTC.IPRE.WORD = 0x0000;
SH7305_INTC.IPRF.WORD = 0x0000;
SH7305_INTC.IPRG.WORD = 0x0000;
SH7305_INTC.IPRH.WORD = 0x0000;
SH7305_INTC.IPRI.WORD = 0x0000;
SH7305_INTC.IPRJ.WORD = 0x0000;
SH7305_INTC.IPRK.WORD = 0x0000;
SH7305_INTC.IPRL.WORD = 0x0000;
// Configure Key Scan (KEYSC)
/* SH7305_INTC.IMR5.KEYI = 1; // Mask KEYSC interrupt.
SH7305_INTC.IPRF.KEYSC = 15; // Disable KEYSC interrupt.
SH7305_KEYSC.CONTROL.KEYIE = 0; // Disable KEYSC interrupt during init.
SH7305_KEYSC.CONTROL.INTMODE = 0b00; // Use default (?) interrupt mode.
SH7305_KEYSC.AUTOFIX.ENABLE = 1; // Enable key bounce fix (?)
SH7305_KEYSC.AUTOFIX.UNKNOWN0 = 0b100; // Unknown, use Casio's value. (autofix)
SH7305_KEYSC.AUTOFIX.UNKNOWN1 = 0b10; // Unknown, use Casio's value. (autofix)
SH7305_KEYSC.SCAN_MODE.UNKNOWN0 = 0b000; // Unknown, use Casio's value. (scan mode)
SH7305_KEYSC.SCAN_MODE.UNKNOWN1 = 0b010; // Unknown, use Casio's value. (scan mode)
SH7305_KEYSC.INTERRUPT.KYCPU_IE = 0b0000100; // Interrupt when one key is pressed or released.
SH7305_KEYSC.SCAN_WAIT.TIME = 0x00; // No time between each interrupt.
SH7305_KEYSC.SCAN_INTERVAL = 0x98; // Unknown, use Casio's value. (scan interval)
SH7305_KEYSC.KYOUTDR.KYO5DT = 0b11; // Trigger when high-impedance state is detected.
SH7305_KEYSC.KYOUTDR.KYO4DT = 0b11; // Trigger when high-impedance state is detected.
SH7305_KEYSC.KYOUTDR.KYO3DT = 0b11; // Trigger when high-impedance state is detected.
SH7305_KEYSC.KYOUTDR.KYO2DT = 0b11; // Trigger when high-impedance state is detected.
SH7305_KEYSC.KYOUTDR.KYO1DT = 0b11; // Trigger when high-impedance state is detected.
SH7305_KEYSC.KYOUTDR.KYO0DT = 0b11; // Trigger when high-impedance state is detected.
SH7305_KEYSC.KYINDR.KYDIR6 = 1; // Scan [F1],[SHIFT],[ALPHA],[x,o,T],[div],[7],[4],[1],[0]
SH7305_KEYSC.KYINDR.KYDIR5 = 1; // Scan [F2],[OPT],[^2],[log],[FD],[8],[5],[2],[.]
SH7305_KEYSC.KYINDR.KYDIR4 = 1; // Scan [F3],[VAR],[^],[ln],[(],[9],[6],[3],[x10]
SH7305_KEYSC.KYINDR.KYDIR3 = 1; // Scan [F4],[MENU],[EXIT],[sin],[)],[DEL],[x],[+],[(-)]
SH7305_KEYSC.KYINDR.KYDIR2 = 1; // Scan [F5],[left],[down],[cos],[,],[%],[-],[EXE]
SH7305_KEYSC.KYINDR.KYDIR1 = 1; // Scan [F6],[up],[right],[tan],[->]
SH7305_KEYSC.KYINDR.KYDIR0 = 1; // Scan [AC/ON]
SH7305_KEYSC.CONTROL.KEYIE = 1; // Enable KEYSC interrupt.
SH7305_INTC.IPRF.KEYSC = 15; // Set KEYSC interrupt priority (max).
SH7305_INTC.IMCR5.KEYI = 1; // Clear KEYSC interrupt mask.
*/
}

View File

@ -0,0 +1,55 @@
.global _t6k11_display
.type _t6k11_display, @function
.text
.align 2
/*
_t6k11_display(void *vram)
This function will display the vram on the screen.
This is the T6K11 drivers, DO NOT USE this function if you are
not absolutly sure that what you are doing.
TODO: use DMA ?
*/
# register organisation:
# r0 Y axis loop.
# r1 LCD register selector.
# r2 LCD data register.
# r3 X axis loop.
# r4 VRAM address.
_t6k11_display:
mov.l r8, @-r15
mov.l r9, @-r15
mov.l 1f, r1
mov.l 2f, r2
mov #4, r6
mov #0, r7
mov #7, r8
mov #192, r5
mov #64, r0
loop_y:
mov.b r6, @r1
mov.b r5, @r2
mov.b r6, @r1
mov.b r7, @r2
mov.b r8, @r1
mov #16, r3
loop_x:
mov.b @r4+, r9
mov.b r9, @r2
dt r3
bf loop_x
dt r0
bf.s loop_y
add #1, r5
mov.l @r15+, r9
rts
mov.l @r15+, r8
.align 4
1: .long 0xb4000000 /* LCD register selector */
2: .long 0xb4010000 /* LCD data register */

7
src/kernel/tty/close.c Normal file
View File

@ -0,0 +1,7 @@
#include <kernel/tty.h>
int tty_close(void)
{
// Do nothing for now.
return (0);
}

18
src/kernel/tty/open.c Normal file
View File

@ -0,0 +1,18 @@
#include <kernel/tty.h>
#include <lib/display.h>
// Internal TTY object.
struct tty_s tty;
int tty_open(void)
{
// Initialize TTY.
tty.cursor.x = 0;
tty.cursor.y = 0;
tty.cursor.max.x = DISPLAY_SCREEN_WIDTH / (KERNEL_FONT_REAL_WIDTH + 1);
tty.cursor.max.y = DISPLAY_SCREEN_HEIGHT / (KERNEL_FONT_REAL_HEIGHT + 1);
// Clear VRAM.
dclear();
return (0);
}

49
src/kernel/tty/write.c Normal file
View File

@ -0,0 +1,49 @@
#include <kernel/tty.h>
#include <lib/display.h>
// Internal TTY object.
extern struct tty_s tty;
static void tty_new_line(void)
{
tty.cursor.x = 0;
if (tty.cursor.y + 1 >= tty.cursor.max.y)
{
dscroll(KERNEL_FONT_REAL_HEIGHT + 1);
return;
}
tty.cursor.y = tty.cursor.y + 1;
return;
}
static void tty_update_cursor(void)
{
tty.cursor.x = tty.cursor.x + 1;
if (tty.cursor.x >= tty.cursor.max.x)
tty_new_line();
}
int tty_write(char const *str, ...)
{
int i;
// Do not handle strig format for now.
// Display string format.
i = -1;
while (str[++i] != '\0')
{
// Check new line char.
if (str[i] == '\n')
tty_new_line();
// Display char.
dascii(
tty.cursor.x * (KERNEL_FONT_REAL_WIDTH + 1),
tty.cursor.y * (KERNEL_FONT_REAL_HEIGHT + 1),
str[i]
);
tty_update_cursor();
}
dupdate();
return (i);
}

27
src/kernel/util/atomic.s Normal file
View File

@ -0,0 +1,27 @@
.global _atomic_start
.global _atomic_end
.type _atomic_start, @function
.type _atomic_end, @function
.align 2
_atomic_start:
stc sr, r1 ! Get SR register.
mov.l .bl_mask, r0 ! Get SR.BL mask.
or r0, r1 ! Set SR.BL to 1.
ldc r1, sr ! Update SR register.
rts ! Exit.
nop ! (db) nop.
_atomic_end:
stc sr, r1 ! Get SR regiter.
mov.l .bl_mask, r0 ! Get SR.BL register.
not r0, r0 ! Get correct mask to remove the SR.BL bit.
and r0, r1 ! Set SR.BL to 0.
ldc r1, sr ! Update SR register.
rts ! Exit.
nop ! (db) nop.
.align 4
.bl_mask: .long (1 << 28)
.end

View File

@ -0,0 +1,38 @@
#include <lib/display.h>
__attribute__((section(".vhex.exception"), interrupt_handler))
void exception_handler(void)
{
uint32_t spc;
uint32_t ssr;
uint32_t sr;
// Get some registers's data.
__asm__ volatile (
"stc spc, %0;"
"stc ssr, %1;"
"stc sr, %2"
: "=r"(spc), "=r"(ssr), "=r"(sr)
:
:
);
// Write exception informations.
dclear();
dprint(0, 0,
"Ho crap ! Exception !\n"
"tra: %#x\n"
"expevt: %#x\n"
"spc: %#x\n"
"ssr: %#x\n"
"sr: %#x",
*((uint32_t *)0xff000020),
*((uint32_t *)0xff000024),
spc,
ssr,
sr
);
dupdate();
while (1);
}

View File

@ -0,0 +1,10 @@
#include <lib/display.h>
__attribute__((section(".vhex.interrupt"), interrupt_handler))
void interrupt_handler(void)
{
dclear();
dprint(0, 0, "Interrupt handler (%#x)\n", *(uint32_t*)0xff000028);
dupdate();
while (1);
}

38
src/kernel/vbr/tlb.c Normal file
View File

@ -0,0 +1,38 @@
#include <lib/display.h>
__attribute__((section(".glados.tlb"), interrupt_handler))
void tlb_handler(void)
{
uint32_t spc;
uint32_t ssr;
uint32_t sr;
// Get some registers's data.
__asm__ volatile (
"stc spc, %0;"
"stc ssr, %1;"
"stc sr, %2"
: "=r"(spc), "=r"(ssr), "=r"(sr)
:
:
);
// Write exception informations.
dclear();
dprint(0, 0,
"Ho crap ! Exception !\n"
"tra: %#x\n"
"expevt: %#x\n"
"spc: %#x\n"
"ssr: %#x\n"
"sr: %#x",
*((uint32_t *)0xff000020),
*((uint32_t *)0xff000024),
spc,
ssr,
sr
);
dupdate();
while (1);
}

View File

@ -1,170 +0,0 @@
#include <utils.h>
#include <syscalls.h>
#include <command.h>
#include <string.h>
//
// check_session()
// Check if the pressed key is [Fx], and switch the current session.
//
static int check_session(unsigned int key, struct vhex_s *vhex)
{
static const unsigned int keys_switch[SESSIONS_SLOT] = {
KEY_F1, KEY_F2, KEY_F3,
KEY_F4, KEY_F5, KEY_F6
};
size_t i;
i = -1;
while (++i < SESSIONS_SLOT && key != keys_switch[i]);
if (i < SESSIONS_SLOT){
vhex->current_session = i;
return (0);
}
return (-1);
}
//
// check_special()
// As explained below, the Casio getkey function has an internal status.
// Here we check if a "special" keys are pressed and update internal Vhex
// "keyboard's status".
//
static int check_special(unsigned int key, struct vhex_s *vhex, struct session_s *session)
{
if (!(key == KEY_OPTN || key == KEY_SHIFT || key == KEY_ALPHA))
return (-1);
if (vhex->insert.mode == LETTER){
vhex->insert.mode = NUMBER;
if (key == KEY_ALPHA)
return (0);
}
if (key == KEY_OPTN){
if (session->mode != COMMAND){
memset(vhex->info, '\0', CMD_LENGHT_MAX);
session->mode = COMMAND;
save_window(1);
}
else
session->mode = (session->anchor == 0x00000000) ? UNUSED : NORMAL;
}
if (key == KEY_SHIFT)
vhex->insert.mode = (vhex->insert.mode == SHIFT) ? NUMBER : SHIFT;
if (key == KEY_ALPHA){
//TODO: update this.
if (vhex->insert.mode == SHIFT)
vhex->insert.mode = CAPS_LOCK;
else if (vhex->insert.mode == CAPS_LOCK)
vhex->insert.mode = NUMBER;
else
vhex->insert.mode = LETTER;
}
return (0);
}
//
// check_alphanum()
// Check if the key pressed is an alphanumeric character and update the user command.
//
/* TODO: find better way to do the job (?) */
static int check_alphanum(unsigned int key, struct vhex_s *vhex, struct session_s *session)
{
static const unsigned int keys_alpha[] = {
KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H,
KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P,
KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X,
KEY_Y, KEY_Z
};
static const unsigned int keys_number[] = {
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4,
KEY_5, KEY_6, KEY_7, KEY_8, KEY_9
};
unsigned int *cache;
size_t size;
size_t end;
size_t i;
char buf;
if (session->mode != COMMAND)
return (-1);
i = -1;
size = strlen(vhex->insert.cmd);
end = (vhex->insert.mode == NUMBER) ? 10 : 26;
cache = (vhex->insert.mode == NUMBER) ? (void *)keys_number : (void *)keys_alpha;
while (++i < end && key != cache[i]);
if (i >= end)
return (-1);
if (size < CMD_LENGHT_MAX){
buf = (vhex->insert.mode == NUMBER) ? '0' + i : 'a' + i;
strcat(vhex->insert.cmd, &buf);
}
if (vhex->insert.mode == LETTER)
vhex->insert.mode = NUMBER;
vhex->history.offset = 0;
return (0);
}
//
// check_arrow()
// Check if the key pressed is an arrow key.
// Here we just check left and right key, but they do not have the same action when
// the mode is COMMAND or not; basically:
// * COMMAND : Udpate the user's command using the history.
// * NORMAL : Move the anchor cursor.
// * UNUSED : Do nothing.
//
static int check_arrow(unsigned int key, struct vhex_s *vhex, struct session_s *session)
{
if (key != KEY_UP && key != KEY_DOWN)
return (-1);
if (session->mode == COMMAND
&& ((key == KEY_UP && vhex->history.offset < vhex->history.deep)
|| (key == KEY_DOWN && vhex->history.offset > 0))){
if (vhex->history.offset == 0)
strcpy(vhex->insert.backup, vhex->insert.cmd);
vhex->history.offset += (key == KEY_UP) ? 1 : -1;
if (vhex->history.offset > 0)
strcpy(vhex->insert.cmd,
history_get(vhex->history.list, vhex->history.offset - 1));
else
strcpy(vhex->insert.cmd, vhex->insert.backup);
}
if (session->mode == NORMAL)
session->cursor += (key == KEY_UP) ? -1 : 1;
return (0);
}
//
// key_handling()
// We need to do several things here; the Casio getkey function handles [SHIFT], [ALPHA]
// and [MENU] key and it is able to do some special thing using the key combination like
// shutdown the calculator, change the brightness or return to the main menu using.
// But when the user press on [SHIFT] or [ALPHA], getkey() return not the same value for
// the same key (and we cannot know the "status").
// So we need to "emulate" the getkey's status and execute the appropriate action with
// the key returned by Casio.
//
void key_handling(struct vhex_s *vhex, struct session_s *session, unsigned int key)
{
size_t size;
if (check_session(key, vhex) == 0
|| check_special(key, vhex, session) == 0
|| check_arrow(key, vhex, session) == 0
|| check_alphanum(key, vhex, session) == 0
|| session->mode != COMMAND)
return;
if (key == KEY_DEL || key == KEY_INS){
size = strlen(vhex->insert.cmd);
if (size > 0)
strncpy(vhex->insert.cmd, vhex->insert.cmd, size - 1);
}
if (key == KEY_SPACE)
strcat(vhex->insert.cmd, " ");
if (key == KEY_QUOTE)
strcat(vhex->insert.cmd, "\"");
if (key == KEY_ENTER){
vhex->insert.mode = NUMBER;
command_entry(session, vhex);
}
}

109
src/lib/display/dascii.c Normal file
View File

@ -0,0 +1,109 @@
#include <lib/display.h>
#include <kernel/types.h>
static const uint8_t kernel_font_bitmap[] = {
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xee, 0xee, 0xef, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xad,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x5e, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x2a, 0x92, 0x11, 0x11, 0x28, 0x00, 0x00, 0x38, 0xbb, 0xab, 0xbb, 0xbb,
0x80, 0x08, 0x23, 0x02, 0x57, 0x31, 0x52, 0x41, 0x22, 0x00, 0x01, 0x51,
0x11, 0x54, 0x41, 0x55, 0x22, 0x27, 0x21, 0x04, 0x0a, 0xc4, 0x40, 0x82,
0xae, 0x0e, 0x04, 0xa2, 0xee, 0xee, 0xe2, 0xee, 0x00, 0x80, 0x24, 0x00,
0x1c, 0xd1, 0x41, 0x04, 0x08, 0x80, 0x11, 0x45, 0x04, 0x45, 0x45, 0x44,
0x88, 0x9c, 0x80, 0x10, 0x2b, 0x09, 0x81, 0x10, 0x02, 0x01, 0x03, 0x8b,
0xb8, 0xbb, 0x8b, 0xb8, 0x20, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xee,
0xec, 0xee, 0xea, 0xee, 0xa8, 0xae, 0xee, 0xee, 0x6e, 0xaa, 0xaa, 0xae,
0xe0, 0xe4, 0x05, 0x55, 0x15, 0x11, 0x14, 0x89, 0x51, 0xd5, 0x55, 0x55,
0x09, 0x55, 0x55, 0x45, 0x10, 0x54, 0x0b, 0xb2, 0x2b, 0xba, 0xb9, 0x13,
0x22, 0xaa, 0xba, 0xb3, 0x92, 0xaa, 0x91, 0x12, 0x10, 0x80, 0x55, 0x54,
0x54, 0x45, 0x52, 0x25, 0x45, 0x55, 0x47, 0x51, 0x25, 0x57, 0x52, 0x44,
0x11, 0x00, 0xca, 0xee, 0xce, 0x8e, 0xae, 0xca, 0xea, 0xae, 0x8e, 0xac,
0x4e, 0x4a, 0xa4, 0xee, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00,
0x90, 0x9a, 0x11, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19,
0x30, 0x39, 0x14, 0x31, 0x52, 0x54, 0x00, 0x42, 0x76, 0x26, 0x35, 0x37,
0x55, 0x55, 0x57, 0x22, 0x20, 0x70, 0x6c, 0x86, 0xee, 0x6c, 0xc4, 0xa4,
0xea, 0xaa, 0xac, 0xc4, 0xaa, 0xa4, 0xa4, 0x84, 0x26, 0xe1, 0x55, 0x15,
0x08, 0x54, 0x89, 0x89, 0x55, 0x58, 0xd0, 0x49, 0x55, 0xd4, 0x90, 0x88,
0x99, 0xc1, 0xb1, 0x99, 0x93, 0x2b, 0xb2, 0x9a, 0xa9, 0x20, 0xa3, 0x19,
0x92, 0xa9, 0x39, 0x93, 0x03, 0x80
};
void dascii(int x, int y, char const c)
{
off_t bitmap_offset_x;
off_t bitmap_offset_y;
off_t vram_offset_y;
int real_width;
int real_height;
uint8_t pixel_test;
int pixel_cursor;
int i;
int j;
// Calculate the charactere position (bitmap)
bitmap_offset_y = (c / KERNEL_FONT_NB_CHAR_X) * (KERNEL_FONT_BITMAP_WIDTH * KERNEL_FONT_BITMAP_CHEIGHT);
bitmap_offset_x = (c - ((c / KERNEL_FONT_NB_CHAR_X) * KERNEL_FONT_NB_CHAR_X)) * KERNEL_FONT_BITMAP_CWIDTH;
// Set default size.
real_width = KERNEL_FONT_REAL_WIDTH;
real_height = KERNEL_FONT_REAL_HEIGHT;
// Check X axis culling.
if (x < 0)
{
bitmap_offset_x = bitmap_offset_x + x;
real_width = KERNEL_FONT_REAL_WIDTH + x;
x = 0;
}
else if (x + KERNEL_FONT_REAL_WIDTH >= DISPLAY_SCREEN_WIDTH)
real_width = DISPLAY_SCREEN_WIDTH - x;
// Check Y axis culling.
if (y < 0)
{
real_height = KERNEL_FONT_REAL_HEIGHT + y;
bitmap_offset_y = bitmap_offset_y + ((-y) * KERNEL_FONT_BITMAP_WIDTH);
y = 0;
}
else if (y + KERNEL_FONT_REAL_HEIGHT >= DISPLAY_SCREEN_HEIGHT)
real_height = DISPLAY_SCREEN_HEIGHT - y;
// Check potential error.
// @note we do not check real_height because the while() while do the job for us.
if (real_width < 0)
return;
// Calculate VRAM buffer starting position.
// @note:
// The screen width size is always 128 and we
// use 4-aligned Video RAM so 32 pixel per "slot"
// and 128 / 32 = 4
// y * 4 can be optimised by used shift operator
// this is why we use y << 2 because 2^2 = 4.
vram_offset_y = y << 2;
// Draw character, pixer per pixel... (x_x)
i = -1;
while (++i < real_height)
{
j = -1;
while (++j < real_width)
{
pixel_cursor = bitmap_offset_x + bitmap_offset_y + j;
pixel_test = 0x80 >> (pixel_cursor & 0x07);
if (pixel_test & kernel_font_bitmap[pixel_cursor >> 3])
{
VRAM[((x + j) >> 5) + vram_offset_y] |= 0x80000000 >> ((x + j) & 0x1f);
}
}
bitmap_offset_y = bitmap_offset_y + KERNEL_FONT_BITMAP_WIDTH;
vram_offset_y = vram_offset_y + 4;
}
}

10
src/lib/display/dclear.c Normal file
View File

@ -0,0 +1,10 @@
#include <lib/display.h>
void dclear(void)
{
int i;
i = 256;
while (--i >= 0)
VRAM[i] = 0x00000000;
}

31
src/lib/display/dprint.c Normal file
View File

@ -0,0 +1,31 @@
#include <lib/stdio.h>
#include <lib/display.h>
#include <stdarg.h>
void dprint(int x, int y, char const *str, ...)
{
char buffer[512];
int default_pos_x;
va_list ap;
int i;
// printf string manipulation.
// TODO: remove me !
va_start(ap, str);
vsprintf(buffer, str, ap);
va_end(ap);
i = -1;
default_pos_x = x;
while (buffer[++i] != '\0')
{
if (buffer[i] == '\n')
{
y = y + KERNEL_FONT_REAL_HEIGHT + 1;
x = default_pos_x;
continue;
}
dascii(x, y, buffer[i]);
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
}

26
src/lib/display/dscroll.c Normal file
View File

@ -0,0 +1,26 @@
#include <lib/display.h>
void dscroll(int lines)
{
int i;
// Scoll n lines
i = 0;
while ((i >> 2) < 63 - lines)
{
VRAM[i + 0] = VRAM[i + (lines << 2) + 0];
VRAM[i + 1] = VRAM[i + (lines << 2) + 1];
VRAM[i + 2] = VRAM[i + (lines << 2) + 2];
VRAM[i + 3] = VRAM[i + (lines << 2) + 3];
i = i + 4;
}
// Clear last n lines
while ((i >> 2) < 64)
{
VRAM[i + 0] = 0x0000;
VRAM[i + 1] = 0x0000;
VRAM[i + 2] = 0x0000;
VRAM[i + 3] = 0x0000;
i = i + 4;
}
}

View File

@ -0,0 +1,8 @@
#include <lib/display.h>
#include <kernel/hardware/t6k11.h>
//FIXME: Check OS 3.00 !
void dupdate(void)
{
t6k11_display(VRAM);
}

10
src/lib/stdio/sprintf.c Normal file
View File

@ -0,0 +1,10 @@
#include <lib/stdio.h>
void sprintf(char *str, char const *format, ...)
{
va_list ap;
va_start(ap, format);
vsprintf(str, format, ap);
va_end(ap);
}

View File

@ -1,4 +1,4 @@
#include <string.h>
#include <lib/stdio.h>
static size_t strbase(char *dest, uint32_t nb, size_t size, int base)
{
@ -43,7 +43,7 @@ static size_t strndump(char *dest, char const *str, size_t size)
return (i);
}
__attribute__((weak)) void vsprintf(char *str, char const *format, va_list ap)
void vsprintf(char *str, char const *format, va_list ap)
{
size_t size;
size_t len;
@ -102,12 +102,3 @@ __attribute__((weak)) void vsprintf(char *str, char const *format, va_list ap)
}
*str = '\0';
}
__attribute__((weak)) void sprintf(char *str, char const *format, ...)
{
va_list ap;
va_start(ap, format);
vsprintf(str, format, ap);
va_end(ap);
}

9
src/lib/string/memcpy.c Normal file
View File

@ -0,0 +1,9 @@
#include <lib/string.h>
#include <lib/display.h>
void *memcpy(void *dest, const void *src, size_t count)
{
for (size_t i = 0 ; i < count ; i = i + 1)
((uint8_t*)dest)[i] = ((uint8_t*)src)[i];
return (dest);
}

View File

@ -1,7 +1,7 @@
#include <utils.h>
#include <lib/string.h>
//TODO: update me :(
__attribute__((weak)) void *memset(void *s, int c, size_t n)
void *memset(void *s, int c, size_t n)
{
while ((int)--n >= 0)
((uint8_t*)s)[n] = c;

View File

@ -1,6 +1,6 @@
#include <string.h>
#include <lib/string.h>
__attribute__((weak)) char *strcat(char *dest, char const *src)
char *strcat(char *dest, char const *src)
{
size_t i;
size_t start;

13
src/lib/string/strcmp.c Normal file
View File

@ -0,0 +1,13 @@
#include <lib/string.h>
int strcmp(const char *s1, const char *s2)
{
if (s1 == NULL || s2 == NULL)
return (0);
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
{
s1 += 1;
s2 += 1;
}
return (*s1 - *s2);
}

View File

@ -1,6 +1,6 @@
#include <string.h>
#include <lib/string.h>
__attribute__((weak)) char *strcpy(char *dest, char const *src)
char *strcpy(char *dest, char const *src)
{
size_t i;
@ -13,7 +13,7 @@ __attribute__((weak)) char *strcpy(char *dest, char const *src)
return (dest);
}
__attribute__((weak)) char *strncpy(char *dest, char const *str, size_t size)
char *strncpy(char *dest, char const *str, size_t size)
{
size_t i;

View File

@ -1,6 +1,6 @@
#include <string.h>
#include <lib/string.h>
__attribute__((weak)) size_t strlen(char const *str)
size_t strlen(char const *str)
{
size_t i;

View File

@ -1,49 +0,0 @@
#include <utils.h>
#include <string.h>
#include <syscalls.h>
//
// vhex_constructor()
// Initialize all information needed by the add-in: session,
// GetKey configuration, ...
//
static void vhex_constructor(struct vhex_s *vhex)
{
size_t i;
i = -1;
memset(vhex->info, '\0', CMD_LENGHT_MAX);
memset(vhex->insert.cmd, '\0', CMD_LENGHT_MAX);
//TODO: Auto detect GetKey configuration !!
vhex->insert.mode = NUMBER;
vhex->history.list = NULL;
vhex->history.offset = 0;
vhex->history.deep = 0;
vhex->current_session = 0;
while (++i < SESSIONS_SLOT){
vhex->session[i].mode = UNUSED;
vhex->session[i].anchor = 0x00000000;
}
}
//
// main()
// User entry, but we need to initialize some information before
// starting the "main loop".
//
int main(void)
{
struct vhex_s vhex;
unsigned int key;
key = 0;
vhex_constructor(&vhex);
while (1){
dclear();
display_instructions(&vhex.session[vhex.current_session]);
display_metainfos(&vhex, &vhex.session[vhex.current_session]);
getkey(&key);
key_handling(&vhex, &vhex.session[vhex.current_session], key);
}
return (0);
}

View File

@ -1,31 +0,0 @@
#include <string.h>
static INLINE int check_base(char n, int base)
{
char max;
max = (base <= 10) ? '0' + base - 1 : ('a' + base - 11);
return ((max < n));
}
//
// atoi_base()
// Wrapped atoi function that takes the base which the number
// (stored in the string) are encoded
//
uint32_t atoi_base(char const *str, int base)
{
uint32_t result;
size_t start;
start = -1;
result = 0;
while (str[++start] != '\0' && check_base(str[start], base) == 0){
result *= base;
if (str[start] <= '9')
result += str[start] - '0';
else
result += (str[start] - 'a') + 10;
}
return (result);
}

View File

@ -1,12 +0,0 @@
#include <string.h>
__attribute__((weak)) int strcmp(const char *s1, const char *s2)
{
if (s1 == NULL || s2 == NULL)
return (0);
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2){
s1 += 1;
s2 += 1;
}
return (*s1 - *s2);
}

View File

@ -1,143 +0,0 @@
#ifndef DEBUG
//# include <commands.h>
# include <syscalls.h>
#else
//# include "commands.h"
# include <stdlib.h>
# include <stdio.h>
#endif
#include <string.h>
#include <errno.h>
// Internal prototypes.
extern int strtotab(int *argc, char ***argv, char const *str);
extern void strtotab_quit(int *argc, char ***argv);
//
// parser_get_word()
// Get the word at the current cursor location.
//
static ssize_t parser_get_word(char ***tab, size_t *tab_pos,
char const *str, int *counter)
{
ssize_t i;
i = -1;
while (str[++i] != '\0' && str[i] != '\n' && str[i] != ' ' && str[i] != '\t');
if (*tab != NULL){
(*tab)[*tab_pos] = (char*)malloc(i + 1);
if ((*tab)[*tab_pos] == NULL)
return (-1);
memset((*tab)[*tab_pos], 0, i + 1);
strncpy((*tab)[(*tab_pos)++], str, i);
}
(*counter)++;
return (i);
}
//
// parser_get_inibitor()
// This function will get the content of an inhibitor (and check if the
// inhibitor characteres are alone or not).
//
static ssize_t parser_get_inibitor(char ***tab, size_t *tab_pos,
char const *str, int *counter)
{
ssize_t i;
i = 0;
while (str[++i] != '\0' && str[i] != '\"');
if (str[i] != '\"')
return (0);
if (*tab != NULL){
(*tab)[*tab_pos] = (char*)malloc(i + 1);
if ((*tab)[*tab_pos] == NULL)
return (-1);
memset((*tab)[*tab_pos], 0, i + 1);
strncpy((*tab)[(*tab_pos)++], str + 1, i - 1);
}
(*counter)++;
return (i + 1);
}
//
// parser_setup_arg()
// This function removes useless spaces, tabs and handle '\"' inhibitor.
// Return the number of word(s) stored in "str".
//
static int parser_entry(char ***tab, char const *str)
{
size_t tab_pos;
ssize_t size;
int counter;
str--;
counter = 0;
tab_pos = 0;
while (*(++str) != '\0' && *str != '\n'){
if (*str == '\"'){
size = parser_get_inibitor(tab, &tab_pos, str, &counter);
if (size < 0)
return (-1);
str += size;
}
if (*str != ' ' && *str != '\t'){
size = parser_get_word(tab, &tab_pos, str, &counter) - 1;
if (size < 0)
return (-1);
str += size;
}
}
return (counter);
}
//
// strtotab()
// Generate word table and indicated the number of word find in the string.
//
int strtotab(int *argc, char ***argv, char const *str)
{
int i;
// Check memory fault.
if (argc == NULL || argv == NULL || str == NULL)
return (EFAULT);
// Get the number of word.
*argv = NULL;
*argc = parser_entry(argv, str);
if (*argc <= 0)
return (EINVAL);
// Alloc tab.
*argv = (char **)malloc(sizeof(char *) * (*argc + 1));
if (*argv == NULL)
return (ENOMEM);
i = *argc;
while (--i >= 0)
(*argv)[i] = NULL;
// Get word.
if (parser_entry(argv, str) != *argc){
strtotab_quit(argc, argv);
return (ENOMEM);
}
(*argv)[*argc] = NULL;
return (0);
}
/* strtotab() - Free all allocated memory generated by "strtotab()" */
void strtotab_quit(int *argc, char ***argv)
{
if (argc == NULL || argv == NULL)
return;
if (*argv == NULL){
*argc = 0;
return;
}
while (--(*argc) >= 0)
free((*argv)[*argc]);
free(*argv);
*argv = NULL;
*argc = 0;
}

View File

@ -1,98 +0,0 @@
.global _casio_GetKey
.global _casio_PrintMini
.global _casio_Bdisp_PutDisp_DD
.global _casio_Bdisp_AllClr_VRAM
.global _casio_Bdisp_DrawLine_VRAM
.global _casio_Bdisp_AreaClr_VRAM
.global _casio_RestoreDisp
.global _casio_SaveDisp
.global _casio_Malloc
.global _casio_Free
.type _casio_GetKey, @function
.type _casio_PrintMini, @function
.type _casio_Bdisp_PutDisp_DD, @function
.type _casio_Bdisp_AllClr_VRAM, @function
.type _casio_Bdisp_DrawLine_VRAM, @function
.type _casio_Bdisp_AreaClr_VRAM, @function
.type _casio_RestoreDisp, @function
.type _casio_SaveDisp, @function
.type _casio_Malloc, @function
.type _casio_Free, @function
.align 2
_casio_GetKey:
mov.l .syscall_tab, r1
mov.l .sys_getkey, r0
jmp @r1
nop
_casio_PrintMini:
mov.l .syscall_tab, r1
mov.l .sys_printMini, r0
jmp @r1
nop
_casio_Bdisp_AllClr_VRAM:
mov.l .syscall_tab, r1
mov.l .sys_clear, r0
jmp @r1
nop
_casio_Bdisp_PutDisp_DD:
mov.l .syscall_tab, r1
mov.l .sys_display, r0
jmp @r1
nop
_casio_Bdisp_DrawLine_VRAM:
mov.l .syscall_tab, r1
mov.l .sys_line, r0
jmp @r1
nop
_casio_Bdisp_AreaClr_VRAM:
mov.l .syscall_tab, r1
mov.l .sys_clear_area, r0
jmp @r1
nop
_casio_RestoreDisp:
mov.l .syscall_tab, r1
mov.l .sys_restore_disp, r0
jmp @r1
nop
_casio_SaveDisp:
mov.l .syscall_tab, r1
mov.l .sys_save_disp, r0
jmp @r1
nop
_casio_Malloc:
mov.l .syscall_tab, r1
mov.l .sys_malloc, r0
jmp @r1
nop
_casio_Free:
mov.l .syscall_tab, r1
mov.l .sys_free, r0
jmp @r1
nop
.align 4
.syscall_tab: .long 0x80010070
.sys_line: .long 0x00000030
.sys_clear: .long 0x00000143 /*Bdisp_AllClr_VRAM */
.sys_getkey: .long 0x0000090f
.sys_display: .long 0x00000028
.sys_printMini: .long 0x00000c4f
.sys_clear_area: .long 0x0000014b
.sys_restore_disp: .long 0x00000814
.sys_save_disp: .long 0x00000813
.sys_malloc: .long 0x00000acd
.sys_free: .long 0x00000acc
.end

34
src/user/main.c Normal file
View File

@ -0,0 +1,34 @@
#include <lib/stdio.h>
#include <lib/display.h>
#include <kernel/tty.h>
int main(void)
{
char *line;
// Open TTY and display entry message
tty_open();
tty_write("Welcome to Vhex !\n");
// Main loop
while (1)
{
// Write input indications.
// TODO: write current working directory ?
tty_write(">");
// Get each line writen by the user.
/*nbread = getline(&line, &size, 0);
if (nbread == EOF)
{
// TODO: check jobs ?
break;
}*/
// TODO: do some job.
}
// Close TTY and return.
tty_close();
return (0);
}

View File

@ -1,31 +0,0 @@
#include <criterion/criterion.h>
// Internal prototypes.
extern uint32_t atoi_base(char const *str, int base);
Test(atoi_base, base_10)
{
uint32_t result;
result = atoi_base("12345", 10);
cr_assert_eq(result, 12345, "returned: %d\n", result);
cr_assert_eq(atoi_base("50926", 10), 50926);
cr_assert_eq(atoi_base("999999", 10), 999999);
}
Test(atoi_base, base_16)
{
uint32_t result;
result = atoi_base("abcdef", 16);
cr_assert_eq(result, 0xabcdef, "returned: %#x\n", result);
cr_assert_eq(atoi_base("50926", 16), 0x50926);
cr_assert_eq(atoi_base("999999", 16), 0x999999);
}
Test(atoi_base, base_error)
{
cr_assert_eq(atoi_base("xxxxxx", 16), 0);
cr_assert_eq(atoi_base("50926x56", 16), 0x50926);
cr_assert_eq(atoi_base("o", 16), 0);
}

View File

@ -1,52 +0,0 @@
#include <criterion/criterion.h>
#include "tests/internal.h"
#include "history.h"
#include <errno.h>
//TODO: write doc.
Test(history, add)
{
struct node *list;
list = NULL;
cr_assert_eq(history_update(&list, "ls -l"), 0);
cr_assert_eq(history_update(&list, "cat -e"), 0);
cr_assert_eq(history_update(NULL, "cat -e"), EFAULT);
// malloc fails.
malloc_hook_update(FAIL_NEXT);
cr_assert_eq(history_update(&list, "cat -e"), ENOMEM);
// Check info.
cr_assert_str_eq(list->data, "cat -e");
cr_assert_str_eq(list->next->data, "ls -l");
cr_assert_null(list->next->next);
}
Test(history, get)
{
struct node *list;
list = NULL;
history_update(&list, "ls -l");
history_update(&list, "cat -e");
cr_assert_str_eq(history_get(list, 1), "ls -l");
cr_assert_str_eq(history_get(list, 0), "cat -e");
cr_assert_null(history_get(list, 4));
}
Test(history, quit)
{
struct node *list;
list = NULL;
history_quit(&list);
history_update(&list, "ls -l");
history_update(&list, "cat -e");
history_update(&list, "test");
history_update(&list, "yes");
history_quit(&list);
history_quit(NULL);
cr_assert_null(list);
}

View File

@ -1,25 +0,0 @@
#ifndef __INTERNAL_H__
# define __INTERNAL_H__
#include <stddef.h>
#include <stdint.h>
//
// status_t - all status available for hook.
// * FAIL_NONE : force malloc to work normaly.
// * FAIL_NEXT : force the next call of malloc to return NULL.
// * FAIL_NEXT_DYN : force X-nth call of malloc to return NULL.
// * FAIL_ALWAYS : force all malloc to return NULL.
//
typedef enum status_e
{
FAIL_NONE,
FAIL_NEXT,
FAIL_ALWAYS,
FAIL_NEXT_DYN
} status_t;
/* malloc_hook_update - udpate the behavior of the malloc hook */
void malloc_hook_update(status_t status, ...);
#endif /*__INTERNAL_H__*/

View File

@ -1,91 +0,0 @@
#include "tests/internal.h"
#include <malloc.h>
#include <stdarg.h>
// Internal prototypes / static symbols.
static void my_malloc_init_hook(void);
static void *my_malloc_hook(size_t size, const void *caller);
static void *old_malloc_hook;
static int hook_dyn_fail;
static int hook_status;
//
// my_malloc_hook()
// This function will replace the current malloc hook by our own
// hook (which can return NULL if we want, it allows us to check
// the behavior of our code).
//
// NOTE:
// "man __malloc_hook" indicate to use "__malloc_initialize_hook"
// which will execute the initialization routine. But from glibc 2.24
// onwards, this variable has been removed from the API.
// So, this is why we use "constructor" attribute to call our routine
// at the beginning of the test.
//
__attribute__((constructor))
static void my_malloc_init_hook(void)
{
old_malloc_hook = __malloc_hook;
__malloc_hook = my_malloc_hook;
hook_status = FAIL_NONE;
}
//
// my_malloc_hook()
// For some tests we need to simulate (properly) a malloc fail; to do this
// we use a malloc hook and add static variables to force him to return
// NULL address.
//
// NOTE:
// All hooks of the glibc will be removed because of their poor behavior
// in multi threaded environment.
// But recently we have seen that the malloc() function is defined by the
// weak symbol, so it is probably possible to override malloc() and do
// the same job.
//
static void *my_malloc_hook(size_t size, const void *caller)
{
void *result;
if (hook_status != FAIL_NONE && hook_status != FAIL_NEXT_DYN){
if (hook_status == FAIL_NEXT)
hook_status = FAIL_NONE;
return (NULL);
}
if (hook_status == FAIL_NEXT_DYN){
hook_dyn_fail -= 1;
if (hook_dyn_fail <= 0){
hook_status = FAIL_NONE;
return (NULL);
}
}
__malloc_hook = old_malloc_hook;
result = malloc(size);
(void)caller;
//printf("caller: %p - area: %p\n", caller, result);
old_malloc_hook = __malloc_hook;
__malloc_hook = my_malloc_hook;
return (result);
}
//
// malloc_hook_udpate()
// This function is the only way to interact with the hook; it will
// define the behavior of malloc:
// * FAIL_NEXT : force the next call of malloc to return NULL.
// * FAIL_NEXT_DYN : force X-nth call of malloc to return NULL.
// * FAIL_ALWAYS : force all malloc return NULL.
// * FAIL_NONE : force malloc to work normally.
//
void malloc_hook_update(status_t status, ...)
{
va_list ap;
hook_dyn_fail = 0;
if (status == FAIL_NEXT_DYN){
va_start(ap, status);
hook_dyn_fail = va_arg(ap, int);
va_end(ap);
}
hook_status = status;
}

View File

@ -1,108 +0,0 @@
#include <criterion/criterion.h>
#include "tests/internal.h"
#include <errno.h>
// Internal prototypes.
extern int strtotab(int *argc, char ***argv, char const *str);
extern void strtotab_quit(int *argc, char ***argv);
Test(strtotab, quote)
{
char **argv;
int argc;
int ret;
ret = strtotab(&argc, &argv, "hey? \"What's \nup?\" yo!\"\n");
cr_expect_eq(ret, 0);
cr_expect_eq(argc, 3);
cr_assert_str_eq(argv[0], "hey?");
cr_assert_str_eq(argv[1], "What's \nup?");
cr_assert_str_eq(argv[2], "yo!\"");
}
Test(strtotab, noword)
{
char **argv;
int argc;
int ret;
ret = strtotab(&argc, &argv, "");
cr_expect_eq(ret, EINVAL);
cr_expect_eq(argc, 0);
cr_assert_null(argv);
}
Test(strtotab, entry_error)
{
char **argv;
int argc;
int ret;
ret = strtotab(NULL, &argv, "aaaaaaaaa aa");
cr_expect_eq(ret, EFAULT);
ret = strtotab(&argc, NULL, "aaaaaaaaa aa");
cr_expect_eq(ret, EFAULT);
ret = strtotab(&argc, &argv, NULL);
cr_expect_eq(ret, EFAULT);
}
Test(strtotab, spaces_tabs)
{
char **argv;
int argc;
int ret;
ret = strtotab(&argc, &argv, "hey? What's\t\t \t up?");
cr_expect_eq(ret, 0);
cr_expect_eq(argc, 3);
cr_assert_str_eq(argv[0], "hey?");
cr_assert_str_eq(argv[1], "What's");
cr_assert_str_eq(argv[2], "up?");
}
Test(strtotab, normal)
{
char **argv;
int argc;
int ret;
ret = strtotab(&argc, &argv, "hey? What's up?\n");
cr_expect_eq(ret, 0);
cr_assert_eq(argc, 3);
cr_assert_str_eq(argv[0], "hey?");
cr_assert_str_eq(argv[1], "What's");
cr_assert_str_eq(argv[2], "up?");
}
Test(strtotab, alloc_fails)
{
char **argv;
int argc;
int ret;
malloc_hook_update(FAIL_NEXT);
ret = strtotab(&argc, &argv, "hey? \"What's up?");
cr_assert_eq(ret, ENOMEM);
malloc_hook_update(FAIL_NEXT_DYN, 2);
ret = strtotab(&argc, &argv, "hey? \"What's up?");
cr_assert_eq(ret, ENOMEM);
malloc_hook_update(FAIL_NEXT_DYN, 2);
ret = strtotab(&argc, &argv, "\"What's\" up?");
cr_assert_eq(ret, ENOMEM);
}
Test(strtotab, quit)
{
char **argv;
int argc;
strtotab(&argc, &argv, "hey? What's up?");
strtotab_quit(&argc, &argv);
cr_assert_eq(argc, 0);
cr_assert_null(argv);
strtotab_quit(NULL, &argv);
strtotab_quit(&argc, NULL);
argv = NULL;
strtotab_quit(&argc, &argv);
}

BIN
vhex.g1a

Binary file not shown.

93
vhex.ld Normal file
View File

@ -0,0 +1,93 @@
OUTPUT_ARCH(sh3)
OUTPUT_FORMAT(elf32-sh)
ENTRY(_start)
MEMORY
{
/*
** bootram is the RAM physical location for global variable
** during the bootloader step.
** This location is realy important because no Casio's OS data
** should be overwrite (specially TLB information stored by Casio).
*/
bootram (rwx) : o = 0x88040000, l = 252k
osram (rwx) : o = 0x8807f000, l = 4k
rom (rx) : o = 0x00300200, l = 512k
}
SECTIONS
{
/*
** ROM sections
*/
. = ORIGIN(rom);
.text : {
*(.pretext)
*(.text)
. = ALIGN(4);
*(.rodata)
*(.rodata.*)
} > rom
/*
** RAM sctions
*/
. = ORIGIN(bootram);
/* BootStrap Stack: should be wiped later ! */
/* (we force the section to be non loadable when the program is run) */
.bss (NOLOAD) : {
_bbss = . ;
*(.bss)
*(COMMON)
. = ALIGN(4);
} > bootram :NONE
_sbss = SIZEOF(.bss);
/* Read-write data going to RAM */
.data : ALIGN(4) {
_bdata_rom = LOADADDR(.data) ;
_bdata_ram = . ;
*(.data)
/* Video RAM space */
_VRAM = ALIGN(4);
. = (. + 1024);
} > bootram AT> rom
_sdata = SIZEOF(.data);
/*
** VBR space !
*/
/* Interrupt / exception handlers */
.vhex : SUBALIGN(4) {
_bvhex_rom = LOADADDR(.vhex) ;
_bvhex_ram = . ;
_vhex_vbr = . - 0x100;
*(.vhex.exception) ;
. = _vhex_vbr + 0x400 ;
*(.vhex.tlb) ;
. = _vhex_vbr + 0x600 ;
*(.vhex.interrupt) ;
. = ALIGN(4);
} > osram AT> rom
_svhex = SIZEOF(.vhex);
/* unwanted section */
/DISCARD/ : {
*(.debug_info)
*(.debug_abbrev)
*(.debug_loc)
*(.debug_aranges)
*(.debug_ranges)
*(.debug_line)
*(.debug_str)
*(.jcr)
*(.eh_frame_hdr)
*(.eh_frame)
*(.comment)
}
}