Compare commits
124 Commits
3.0.2
...
4.0.1-hotf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0233b796e | ||
|
|
99b45cac7b | ||
|
|
ee212a5156 | ||
|
|
dfe42c3991 | ||
|
|
c895266f34 | ||
|
|
6881075fc8 | ||
|
|
09cd6e2bd1 | ||
|
|
23cc913bf2 | ||
|
|
eb3fc13385 | ||
|
|
35a6bd9b41 | ||
|
|
e87301e160 | ||
|
|
e96ea63479 | ||
|
|
c24e028960 | ||
|
|
5a12d0c120 | ||
|
|
785549a9c8 | ||
|
|
b5f5701e58 | ||
|
|
9042132edf | ||
|
|
5909782c36 | ||
|
|
11c69d4cb1 | ||
|
|
80d6ad6a00 | ||
|
|
13d320a355 | ||
|
|
b9b6e07eb0 | ||
|
|
80ee915bfd | ||
|
|
42fa0903e7 | ||
|
|
90ae8f3176 | ||
|
|
e4747b2344 | ||
|
|
848a91dff7 | ||
|
|
87ae4aac62 | ||
|
|
b678673d95 | ||
|
|
6ad5c7b5f6 | ||
|
|
9eef3d7b47 | ||
|
|
36e120a4ea | ||
|
|
a09b720790 | ||
|
|
6e2a5f0523 | ||
|
|
b7f110a41c | ||
|
|
2d6c6593af | ||
|
|
9a86025291 | ||
|
|
c9bb7e7766 | ||
|
|
f5fa98c725 | ||
|
|
0b3d4bf55c | ||
|
|
aa82664187 | ||
|
|
3f30b6c027 | ||
|
|
62d93636d0 | ||
|
|
425f3e82b1 | ||
|
|
c6ce5e87ba | ||
|
|
87fb740602 | ||
|
|
6a54e31d8e | ||
|
|
74b6106f26 | ||
|
|
192568b686 | ||
|
|
094d43916c | ||
|
|
ba2cc83b8d | ||
|
|
39d2ef3e8a | ||
|
|
797a5f95b5 | ||
|
|
205e0510d1 | ||
|
|
d68912f5e5 | ||
|
|
40d8bb8ba4 | ||
|
|
beb6b1ec33 | ||
|
|
523a6bb05d | ||
|
|
0a007bf3c3 | ||
|
|
e42cc4c8eb | ||
|
|
f5a4eec6bb | ||
|
|
fb3951435f | ||
|
|
d3aa69308e | ||
|
|
058853d7d2 | ||
|
|
fd7ebd1cef | ||
|
|
4b5b8e80a2 | ||
|
|
b8496cb935 | ||
|
|
1a533d95af | ||
|
|
b40258f294 | ||
|
|
e9fb276e46 | ||
|
|
d4f95da062 | ||
|
|
8807af9109 | ||
|
|
d2a0786875 | ||
|
|
dea3294445 | ||
|
|
b3d3dd31dc | ||
|
|
6ecf8daef7 | ||
|
|
e448d6bafa | ||
|
|
db3ba94b5a | ||
|
|
e423a612ce | ||
|
|
5b981bb144 | ||
|
|
f48447f9f5 | ||
|
|
987b7e8765 | ||
|
|
f5623a4fdc | ||
|
|
60eac955f6 | ||
|
|
5bd4dd3a48 | ||
|
|
6543a245c4 | ||
|
|
e41971c7d6 | ||
|
|
b730c060c7 | ||
|
|
9b47a0da33 | ||
|
|
3ab95dfd64 | ||
|
|
d7ebd9fdbe | ||
|
|
27350c0a5f | ||
|
|
e49f184f9b | ||
|
|
2311c52ebf | ||
|
|
3cd78d6efd | ||
|
|
b06085915d | ||
|
|
00fc334764 | ||
|
|
3c640e23b1 | ||
|
|
8c6e70b63d | ||
|
|
0bef41c033 | ||
|
|
91af9b4437 | ||
|
|
65a28d8ef6 | ||
|
|
623634b515 | ||
|
|
2ddc7ae2a9 | ||
|
|
804ba3495c | ||
|
|
e4d80261fa | ||
|
|
ed072abb6b | ||
|
|
050e7e9ba2 | ||
|
|
fec68fbe45 | ||
|
|
98c36cafd3 | ||
|
|
24a90ebc99 | ||
|
|
a1ae52e8ac | ||
|
|
bb4361c991 | ||
|
|
e81e418b1e | ||
|
|
adc54c9881 | ||
|
|
347513a037 | ||
|
|
d8f0c714b6 | ||
|
|
ae6c0dd9f9 | ||
|
|
3667da9b81 | ||
|
|
946c43549f | ||
|
|
b06b3b2ac9 | ||
|
|
a80a1cf949 | ||
|
|
3a079f11c5 | ||
|
|
3499ad1549 |
12
.github/workflows/builder.yml
vendored
12
.github/workflows/builder.yml
vendored
@@ -5,15 +5,21 @@ on: [push, pull_request]
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: devkitpro/devkita64_devkitarm
|
container: devkitpro/devkita64
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
|
|
||||||
- name: Build TegraExplorer
|
- name: Build TegraExplorer
|
||||||
run: make -j$(nproc)
|
run: |
|
||||||
|
sudo apt update -y
|
||||||
|
sudo apt install build-essential -y
|
||||||
|
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
with:
|
with:
|
||||||
name: TegraExplorer
|
name: TegraExplorer
|
||||||
path: output/TegraExplorer.bin
|
path: |
|
||||||
|
output/TegraExplorer.bin
|
||||||
|
output/TegraExplorer_small.bin
|
||||||
|
|||||||
14
.gitignore
vendored
14
.gitignore
vendored
@@ -2,3 +2,17 @@
|
|||||||
build
|
build
|
||||||
output
|
output
|
||||||
research
|
research
|
||||||
|
|
||||||
|
loader/payload_00.h
|
||||||
|
|
||||||
|
loader/payload_01.h
|
||||||
|
|
||||||
|
source/script/Debug
|
||||||
|
source/script/*.te
|
||||||
|
source/script/.vs
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
source/script/builtin.c
|
||||||
|
|
||||||
|
source/script/builtin.h
|
||||||
|
|||||||
49
Makefile
49
Makefile
@@ -8,10 +8,11 @@ include $(DEVKITARM)/base_rules
|
|||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
IPL_LOAD_ADDR := 0x40003000
|
IPL_LOAD_ADDR := 0x40008000
|
||||||
LPVERSION_MAJOR := 3
|
LPVERSION_MAJOR := 4
|
||||||
LPVERSION_MINOR := 0
|
LPVERSION_MINOR := 0
|
||||||
LPVERSION_BUGFX := 2
|
LPVERSION_BUGFX := 1
|
||||||
|
LPVERSION := \"$(LPVERSION_MAJOR).$(LPVERSION_MINOR).$(LPVERSION_BUGFX)\"
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
@@ -21,10 +22,13 @@ OUTPUTDIR := output
|
|||||||
SOURCEDIR = source
|
SOURCEDIR = source
|
||||||
BDKDIR := bdk
|
BDKDIR := bdk
|
||||||
BDKINC := -I./$(BDKDIR)
|
BDKINC := -I./$(BDKDIR)
|
||||||
|
LOADERDIR := ./loader
|
||||||
|
LZ77DIR := ./tools/lz
|
||||||
|
BIN2CDIR := ./tools/bin2c
|
||||||
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
|
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
|
||||||
VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
|
VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
|
||||||
|
|
||||||
OBJS = $(patsubst $(SOURCEDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \
|
OBJS = $(BUILDDIR)/$(TARGET)/script/builtin.c $(patsubst $(SOURCEDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \
|
||||||
$(patsubst $(SOURCEDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \
|
$(patsubst $(SOURCEDIR)/%.c, $(BUILDDIR)/$(TARGET)/%.o, \
|
||||||
$(call rwildcard, $(SOURCEDIR), *.S *.c)))
|
$(call rwildcard, $(SOURCEDIR), *.S *.c)))
|
||||||
OBJS += $(patsubst $(BDKDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \
|
OBJS += $(patsubst $(BDKDIR)/%.S, $(BUILDDIR)/$(TARGET)/%.o, \
|
||||||
@@ -37,7 +41,7 @@ FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"'
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
|
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
|
||||||
CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX)
|
CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX) -DLP_VER=$(LPVERSION)
|
||||||
CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
|
CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
|
||||||
|
|
||||||
# 0: UART_A, 1: UART_B.
|
# 0: UART_A, 1: UART_B.
|
||||||
@@ -53,16 +57,30 @@ LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defs
|
|||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(OUTPUTDIR)/$(TARGET).bin
|
all: $(OUTPUTDIR)/$(TARGET)_small.bin
|
||||||
@echo -n "Payload size is "
|
|
||||||
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
||||||
@echo $(BIN_SIZE)
|
@echo "Payload size is $(BIN_SIZE)"
|
||||||
|
$(eval COMPR_BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET)_small.bin))
|
||||||
|
@echo "Compressed Payload size is $(COMPR_BIN_SIZE)"
|
||||||
|
|
||||||
@echo "Max size is 126296 Bytes."
|
@echo "Max size is 126296 Bytes."
|
||||||
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
|
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
|
||||||
|
@if [ ${COMPR_BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mCompressed Payload size exceeds limit!\e[0m"; fi
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(BUILDDIR)
|
@rm -rf $(BUILDDIR)
|
||||||
@rm -rf $(OUTPUTDIR)
|
@rm -rf $(OUTPUTDIR)
|
||||||
|
@rm -rf $(LOADERDIR)/payload_*.h
|
||||||
|
|
||||||
|
$(OUTPUTDIR)/$(TARGET)_small.bin: $(OUTPUTDIR)/$(TARGET).bin
|
||||||
|
@$(MAKE) -C $(LZ77DIR)
|
||||||
|
@$(LZ77DIR)/lz77 $(OUTPUTDIR)/$(TARGET).bin
|
||||||
|
@$(MAKE) -C $(BIN2CDIR)
|
||||||
|
@$(BIN2CDIR)/bin2c $(OUTPUTDIR)/$(TARGET).bin.00.lz payload_00 > $(LOADERDIR)/payload_00.h
|
||||||
|
@$(BIN2CDIR)/bin2c $(OUTPUTDIR)/$(TARGET).bin.01.lz payload_01 > $(LOADERDIR)/payload_01.h
|
||||||
|
@rm -rf $(OUTPUTDIR)/$(TARGET).bin.*.lz
|
||||||
|
|
||||||
|
$(MAKE) -C $(LOADERDIR) PAYLOAD_NAME=$(TARGET)_small
|
||||||
|
|
||||||
$(OUTPUTDIR)/$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
$(OUTPUTDIR)/$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
@@ -86,3 +104,18 @@ $(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.c
|
|||||||
$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.S
|
$(BUILDDIR)/$(TARGET)/%.o: $(BDKDIR)/%.S
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(BUILDDIR)/$(TARGET)/script/builtin.o: $(BUILDDIR)/$(TARGET)/script/builtin.c
|
||||||
|
@mkdir -p "$(@D)"
|
||||||
|
$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||||
|
|
||||||
|
$(BUILDDIR)/$(TARGET)/script/builtin.c: scripts/*.te
|
||||||
|
@mkdir -p "$(@D)"
|
||||||
|
@mkdir -p "$(BUILDDIR)/$(TARGET)/scripts"
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@py ts-minifier.py --such-meme -d "$(BUILDDIR)/$(TARGET)/scripts" $(wildcard scripts/*.te)
|
||||||
|
@py te2c.py "$(BUILDDIR)/$(TARGET)/script/builtin" "$(BUILDDIR)/$(TARGET)/scripts"
|
||||||
|
else
|
||||||
|
@python3 ts-minifier.py --such-meme -d "$(BUILDDIR)/$(TARGET)/scripts" $(wildcard scripts/*.te)
|
||||||
|
@python3 te2c.py "$(BUILDDIR)/$(TARGET)/script/builtin" "$(BUILDDIR)/$(TARGET)/scripts"
|
||||||
|
endif
|
||||||
|
|||||||
@@ -507,6 +507,11 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
|
|||||||
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
|
PWM(PWM_CONTROLLER_PWM_CSR_0) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 display_get_backlight_brightness()
|
||||||
|
{
|
||||||
|
return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
static void _display_panel_and_hw_end(bool no_panel_deinit)
|
static void _display_panel_and_hw_end(bool no_panel_deinit)
|
||||||
{
|
{
|
||||||
if (no_panel_deinit)
|
if (no_panel_deinit)
|
||||||
|
|||||||
@@ -650,8 +650,9 @@
|
|||||||
* [10] 81 [26]: JDI LPM062M326A
|
* [10] 81 [26]: JDI LPM062M326A
|
||||||
* [10] 96 [09]: JDI LAM062M109A
|
* [10] 96 [09]: JDI LAM062M109A
|
||||||
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
|
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
|
||||||
* [20] 95 [0F]: InnoLux P062CCA-AZ2
|
* [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1)
|
||||||
* [20] 96 [0F]: InnoLux P062CCA-AZ3
|
* [20] 96 [0F]: InnoLux P062CCA-AZ3 [UNCONFIRMED MODEL REV]
|
||||||
|
* [20] 98 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV]
|
||||||
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
|
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
|
||||||
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
|
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
|
||||||
*
|
*
|
||||||
@@ -706,6 +707,7 @@ void display_color_screen(u32 color);
|
|||||||
/*! Switches screen backlight ON/OFF. */
|
/*! Switches screen backlight ON/OFF. */
|
||||||
void display_backlight(bool enable);
|
void display_backlight(bool enable);
|
||||||
void display_backlight_brightness(u32 brightness, u32 step_delay);
|
void display_backlight_brightness(u32 brightness, u32 step_delay);
|
||||||
|
u32 display_get_backlight_brightness();
|
||||||
|
|
||||||
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
|
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
|
||||||
u32 *display_init_framebuffer_pitch();
|
u32 *display_init_framebuffer_pitch();
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "elfload/elfload.h"
|
#include "elfload/elfload.h"
|
||||||
#include <module.h>
|
#include <module.h>
|
||||||
#include <mem/heap.h>
|
#include <mem/heap.h>
|
||||||
|
#include <power/max7762x.h>
|
||||||
#include <storage/nx_sd.h>
|
#include <storage/nx_sd.h>
|
||||||
#include <utils/types.h>
|
#include <utils/types.h>
|
||||||
|
|
||||||
@@ -43,6 +44,10 @@ static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig)
|
|||||||
bdkParameters->memset = (memset_t)&memset;
|
bdkParameters->memset = (memset_t)&memset;
|
||||||
bdkParameters->sharedHeap = &_heap;
|
bdkParameters->sharedHeap = &_heap;
|
||||||
|
|
||||||
|
// Extra functions.
|
||||||
|
bdkParameters->extension_magic = IANOS_EXT0;
|
||||||
|
bdkParameters->reg_voltage_set = (reg_voltage_set_t)&max7762x_regulator_set_voltage;
|
||||||
|
|
||||||
entrypoint(moduleConfig, bdkParameters);
|
entrypoint(moduleConfig, bdkParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Joy-Con UART driver for Nintendo Switch
|
* Joy-Con UART driver for Nintendo Switch
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 CTCaer
|
* Copyright (c) 2019-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -463,7 +463,7 @@ static void jc_rcv_pkt(joycon_ctxt_t *jc)
|
|||||||
|
|
||||||
// Check if device stopped sending data.
|
// Check if device stopped sending data.
|
||||||
u32 uart_irq = uart_get_IIR(jc->uart);
|
u32 uart_irq = uart_get_IIR(jc->uart);
|
||||||
if ((uart_irq & 0x8) != 0x8)
|
if (uart_irq != UART_IIR_REDI)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
|
u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100);
|
||||||
@@ -694,9 +694,15 @@ retry:
|
|||||||
|
|
||||||
void jc_deinit()
|
void jc_deinit()
|
||||||
{
|
{
|
||||||
|
// Disable power.
|
||||||
|
jc_power_supply(UART_B, false);
|
||||||
|
jc_power_supply(UART_C, false);
|
||||||
|
|
||||||
|
// Turn off Joy-Con detect.
|
||||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
|
||||||
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||||
|
|
||||||
|
// Send sleep command.
|
||||||
u8 data = HCI_STATE_SLEEP;
|
u8 data = HCI_STATE_SLEEP;
|
||||||
|
|
||||||
if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
|
if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
|
||||||
@@ -710,8 +716,9 @@ void jc_deinit()
|
|||||||
jc_rcv_pkt(&jc_l);
|
jc_rcv_pkt(&jc_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
jc_power_supply(UART_B, false);
|
// Disable UART B and C clocks.
|
||||||
jc_power_supply(UART_C, false);
|
clock_disable_uart(UART_B);
|
||||||
|
clock_disable_uart(UART_C);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jc_init_conn(joycon_ctxt_t *jc)
|
static void jc_init_conn(joycon_ctxt_t *jc)
|
||||||
@@ -878,14 +885,14 @@ void jc_init_hw()
|
|||||||
pinmux_config_uart(UART_C);
|
pinmux_config_uart(UART_C);
|
||||||
|
|
||||||
// Ease the stress to APB.
|
// Ease the stress to APB.
|
||||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||||
|
|
||||||
// Enable UART B and C clocks.
|
// Enable UART B and C clocks.
|
||||||
clock_enable_uart(UART_B);
|
clock_enable_uart(UART_B);
|
||||||
clock_enable_uart(UART_C);
|
clock_enable_uart(UART_C);
|
||||||
|
|
||||||
// Restore OC.
|
// Restore OC.
|
||||||
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST);
|
bpmp_clk_rate_set(prev_fid);
|
||||||
|
|
||||||
// Turn Joy-Con detect on.
|
// Turn Joy-Con detect on.
|
||||||
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
|
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ touch_panel_info_t *touch_get_panel_vendor()
|
|||||||
{
|
{
|
||||||
u8 buf[5] = {0};
|
u8 buf[5] = {0};
|
||||||
u8 cmd = STMFTS_VENDOR_GPIO_STATE;
|
u8 cmd = STMFTS_VENDOR_GPIO_STATE;
|
||||||
|
static touch_panel_info_t panel_info = { -2, 0, 0, 0, ""};
|
||||||
|
|
||||||
if (touch_command(STMFTS_VENDOR, &cmd, 1))
|
if (touch_command(STMFTS_VENDOR, &cmd, 1))
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -220,13 +221,20 @@ touch_panel_info_t *touch_get_panel_vendor()
|
|||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
// Touch panel not found, return current gpios.
|
||||||
|
panel_info.gpio0 = buf[0];
|
||||||
|
panel_info.gpio1 = buf[1];
|
||||||
|
panel_info.gpio2 = buf[2];
|
||||||
|
|
||||||
|
return &panel_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
int touch_get_fw_info(touch_fw_info_t *fw)
|
int touch_get_fw_info(touch_fw_info_t *fw)
|
||||||
{
|
{
|
||||||
u8 buf[8] = {0};
|
u8 buf[8] = {0};
|
||||||
|
|
||||||
|
memset(fw, 0, sizeof(touch_fw_info_t));
|
||||||
|
|
||||||
// Get fw address info.
|
// Get fw address info.
|
||||||
u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 };
|
u8 cmd[3] = { STMFTS_RW_FRAMEBUFFER_REG, 0, 0x60 };
|
||||||
int res = touch_read_reg(cmd, 3, buf, 3);
|
int res = touch_read_reg(cmd, 3, buf, 3);
|
||||||
@@ -318,7 +326,7 @@ int touch_get_fb_info(u8 *buf)
|
|||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
|
|
||||||
for (u32 i = 0; i < 0x10000; i+=4)
|
for (u32 i = 0; i < 0x10000; i += 4)
|
||||||
{
|
{
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
@@ -392,11 +400,11 @@ static int touch_init()
|
|||||||
|
|
||||||
int touch_power_on()
|
int touch_power_on()
|
||||||
{
|
{
|
||||||
// Enable LDO6 for touchscreen VDD/AVDD supply.
|
// Enable LDO6 for touchscreen AVDD supply.
|
||||||
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
|
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
|
||||||
max7762x_regulator_enable(REGULATOR_LDO6, true);
|
max7762x_regulator_enable(REGULATOR_LDO6, true);
|
||||||
|
|
||||||
// Configure touchscreen GPIO.
|
// Configure touchscreen VDD GPIO.
|
||||||
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
|
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
|
||||||
gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO);
|
gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO);
|
||||||
gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE);
|
gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE);
|
||||||
@@ -410,7 +418,7 @@ int touch_power_on()
|
|||||||
// Configure Touscreen and GCAsic shared GPIO.
|
// Configure Touscreen and GCAsic shared GPIO.
|
||||||
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2;
|
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2;
|
||||||
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2;
|
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2;
|
||||||
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO);
|
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect.
|
||||||
|
|
||||||
// Initialize I2C3.
|
// Initialize I2C3.
|
||||||
pinmux_config_i2c(I2C_3);
|
pinmux_config_i2c(I2C_3);
|
||||||
|
|||||||
@@ -839,10 +839,12 @@ int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst
|
|||||||
int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
|
int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
LZ4_stream_t ctx;
|
LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
|
||||||
LZ4_stream_t* const ctxPtr = &ctx;
|
LZ4_stream_t* const ctxPtr = ctx;
|
||||||
result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
|
result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
|
||||||
|
|
||||||
|
FREEMEM(ctx);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,13 +859,18 @@ int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxO
|
|||||||
/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
|
/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
|
||||||
int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
|
int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
|
||||||
{
|
{
|
||||||
LZ4_stream_t ctx;
|
int result;
|
||||||
LZ4_resetStream(&ctx);
|
LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));
|
||||||
|
LZ4_resetStream(ctx);
|
||||||
|
|
||||||
if (inputSize < LZ4_64Klimit)
|
if (inputSize < LZ4_64Klimit)
|
||||||
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
|
result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
|
||||||
else
|
else
|
||||||
return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
|
result = LZ4_compress_generic(&ctx->internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
|
||||||
|
|
||||||
|
FREEMEM(ctx);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1045,11 +1052,13 @@ static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src,
|
|||||||
|
|
||||||
int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
|
int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
|
||||||
{
|
{
|
||||||
LZ4_stream_t ctxBody;
|
LZ4_stream_t* ctxBody = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));;
|
||||||
LZ4_stream_t* ctx = &ctxBody;
|
LZ4_stream_t* ctx = ctxBody;
|
||||||
|
|
||||||
int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
|
int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
|
||||||
|
|
||||||
|
FREEMEM(ctxBody);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ typedef enum {
|
|||||||
DRIVE_SD = 0,
|
DRIVE_SD = 0,
|
||||||
DRIVE_RAM = 1,
|
DRIVE_RAM = 1,
|
||||||
DRIVE_EMMC = 2,
|
DRIVE_EMMC = 2,
|
||||||
DRIVE_BIS = 3
|
DRIVE_BIS = 3,
|
||||||
|
DRIVE_EMU = 4
|
||||||
} DDRIVE;
|
} DDRIVE;
|
||||||
|
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff);
|
|||||||
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
|
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
|
||||||
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
|
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
|
||||||
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
|
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
|
||||||
|
#define SET_SECTOR_OFFSET 5 /* Set media logical offset */
|
||||||
|
|
||||||
/* Generic command (Not used by FatFs) */
|
/* Generic command (Not used by FatFs) */
|
||||||
#define CTRL_POWER 5 /* Get/Set power status */
|
#define CTRL_POWER 5 /* Get/Set power status */
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/*Log settings*/
|
/*Log settings*/
|
||||||
#ifdef DEBUG_UART_PORT
|
#ifdef DEBUG_UART_LV_LOG
|
||||||
# define USE_LV_LOG 1 /*Enable/disable the log module*/
|
# define USE_LV_LOG 1 /*Enable/disable the log module*/
|
||||||
#else
|
#else
|
||||||
# define USE_LV_LOG 0 /*Enable/disable the log module*/
|
# define USE_LV_LOG 0 /*Enable/disable the log module*/
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ void lv_log_add(lv_log_level_t level, const char * file, int line, const char *
|
|||||||
|
|
||||||
if(level >= LV_LOG_LEVEL) {
|
if(level >= LV_LOG_LEVEL) {
|
||||||
|
|
||||||
#if LV_LOG_PRINTF
|
#if LV_LOG_PRINTF && defined(DEBUG_UART_PORT)
|
||||||
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"};
|
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"};
|
||||||
char *log = (char *)malloc(0x1000);
|
char *log = (char *)malloc(0x1000);
|
||||||
s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line);
|
s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line);
|
||||||
|
|||||||
@@ -99,10 +99,9 @@ bool save_data_file_write(save_data_file_ctx_t *ctx, uint64_t *out_bytes_written
|
|||||||
if (!save_data_file_validate_write_params(ctx, offset, count, ctx->mode, &is_resize_needed))
|
if (!save_data_file_validate_write_params(ctx, offset, count, ctx->mode, &is_resize_needed))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (is_resize_needed) {
|
if (!save_data_file_set_size(ctx, offset + count))
|
||||||
if (!save_data_file_set_size(ctx, offset + count))
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_bytes_written = save_allocation_table_storage_write(&ctx->base_storage, buffer, offset, count);
|
*out_bytes_written = save_allocation_table_storage_write(&ctx->base_storage, buffer, offset, count);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -104,21 +104,21 @@ u32 minerva_init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz;
|
mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz;
|
||||||
mtc_cfg->rate_to = 204000;
|
mtc_cfg->rate_to = FREQ_204;
|
||||||
mtc_cfg->train_mode = OP_TRAIN;
|
mtc_cfg->train_mode = OP_TRAIN;
|
||||||
minerva_cfg(mtc_cfg, NULL);
|
minerva_cfg(mtc_cfg, NULL);
|
||||||
mtc_cfg->rate_to = 800000;
|
mtc_cfg->rate_to = FREQ_800;
|
||||||
minerva_cfg(mtc_cfg, NULL);
|
minerva_cfg(mtc_cfg, NULL);
|
||||||
mtc_cfg->rate_to = 1600000;
|
mtc_cfg->rate_to = FREQ_1600;
|
||||||
minerva_cfg(mtc_cfg, NULL);
|
minerva_cfg(mtc_cfg, NULL);
|
||||||
|
|
||||||
// FSP WAR.
|
// FSP WAR.
|
||||||
mtc_cfg->train_mode = OP_SWITCH;
|
mtc_cfg->train_mode = OP_SWITCH;
|
||||||
mtc_cfg->rate_to = 800000;
|
mtc_cfg->rate_to = FREQ_800;
|
||||||
minerva_cfg(mtc_cfg, NULL);
|
minerva_cfg(mtc_cfg, NULL);
|
||||||
|
|
||||||
// Switch to max.
|
// Switch to max.
|
||||||
mtc_cfg->rate_to = 1600000;
|
mtc_cfg->rate_to = FREQ_1600;
|
||||||
minerva_cfg(mtc_cfg, NULL);
|
minerva_cfg(mtc_cfg, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -139,6 +139,23 @@ void minerva_change_freq(minerva_freq_t freq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void minerva_prep_boot_freq()
|
||||||
|
{
|
||||||
|
if (!minerva_cfg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
|
||||||
|
|
||||||
|
// Check if there's RAM OC. If not exit.
|
||||||
|
if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// FSP WAR.
|
||||||
|
minerva_change_freq(FREQ_204);
|
||||||
|
// Scale down to 800 MHz boot freq.
|
||||||
|
minerva_change_freq(FREQ_800);
|
||||||
|
}
|
||||||
|
|
||||||
void minerva_periodic_training()
|
void minerva_periodic_training()
|
||||||
{
|
{
|
||||||
if (!minerva_cfg)
|
if (!minerva_cfg)
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ typedef enum
|
|||||||
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
|
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
|
||||||
u32 minerva_init();
|
u32 minerva_init();
|
||||||
void minerva_change_freq(minerva_freq_t freq);
|
void minerva_change_freq(minerva_freq_t freq);
|
||||||
|
void minerva_prep_boot_freq();
|
||||||
void minerva_periodic_training();
|
void minerva_periodic_training();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,9 +20,9 @@
|
|||||||
//#define IPL_STACK_TOP 0x4003FF00
|
//#define IPL_STACK_TOP 0x4003FF00
|
||||||
/* --- BIT/BCT: 0x40000000 - 0x40003000 --- */
|
/* --- BIT/BCT: 0x40000000 - 0x40003000 --- */
|
||||||
/* --- IPL: 0x40003000 - 0x40028000 --- */
|
/* --- IPL: 0x40003000 - 0x40028000 --- */
|
||||||
#define LDR_LOAD_ADDR 0x40007000
|
#define LDR_LOAD_ADDR 0x40003000
|
||||||
|
|
||||||
#define IPL_LOAD_ADDR 0x40003000
|
#define IPL_LOAD_ADDR 0x40008000
|
||||||
#define IPL_SZ_MAX 0x20000 // 128KB.
|
#define IPL_SZ_MAX 0x20000 // 128KB.
|
||||||
|
|
||||||
/* --- XUSB EP context and TRB ring buffers --- */
|
/* --- XUSB EP context and TRB ring buffers --- */
|
||||||
|
|||||||
@@ -21,10 +21,13 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <mem/heap.h>
|
#include <mem/heap.h>
|
||||||
|
|
||||||
|
#define IANOS_EXT0 0x304E4149
|
||||||
|
|
||||||
// Module Callback
|
// Module Callback
|
||||||
typedef void (*cbMainModule_t)(const char *s);
|
typedef void (*cbMainModule_t)(const char *s);
|
||||||
typedef void (*memcpy_t)(void *, void *, size_t);
|
typedef void (*memcpy_t)(void *, void *, size_t);
|
||||||
typedef void (*memset_t)(void *, int, size_t);
|
typedef void (*memset_t)(void *, int, size_t);
|
||||||
|
typedef int (*reg_voltage_set_t)(u32, u32);
|
||||||
|
|
||||||
typedef struct _bdkParams_t
|
typedef struct _bdkParams_t
|
||||||
{
|
{
|
||||||
@@ -33,6 +36,8 @@ typedef struct _bdkParams_t
|
|||||||
heap_t *sharedHeap;
|
heap_t *sharedHeap;
|
||||||
memcpy_t memcpy;
|
memcpy_t memcpy;
|
||||||
memset_t memset;
|
memset_t memset;
|
||||||
|
u32 extension_magic;
|
||||||
|
reg_voltage_set_t reg_voltage_set;
|
||||||
} *bdkParams_t;
|
} *bdkParams_t;
|
||||||
|
|
||||||
// Module Entrypoint
|
// Module Entrypoint
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ typedef struct _max77620_regulator_t
|
|||||||
|
|
||||||
static const max77620_regulator_t _pmic_regulators[] = {
|
static const max77620_regulator_t _pmic_regulators[] = {
|
||||||
{ "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
|
{ "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
|
||||||
{ "sd1", 12500, 600000, 1125000, 1125000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
|
{ "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
|
||||||
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
|
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
|
||||||
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
|
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
|
||||||
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
|
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },
|
||||||
@@ -328,6 +328,7 @@ void max77620_config_default()
|
|||||||
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0);
|
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stock HOS: disabled.
|
||||||
void max77620_low_battery_monitor_config(bool enable)
|
void max77620_low_battery_monitor_config(bool enable)
|
||||||
{
|
{
|
||||||
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,
|
_max7762x_set_reg(MAX77620_I2C_ADDR, MAX77620_REG_CNFGGLBL1,
|
||||||
|
|||||||
@@ -32,11 +32,11 @@
|
|||||||
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
||||||
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
|
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
|
||||||
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
|
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
|
||||||
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 |
|
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 0.85V (AO, pcv)
|
||||||
* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
|
* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
|
||||||
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V
|
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V (pcv)
|
||||||
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 |
|
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
||||||
* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 |
|
* ldo8 | XUSB, DP, MCU | 50000 | 800000 | 1050000 | 2800000 | 1.05V/2.8V (pcv)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -135,10 +135,10 @@
|
|||||||
#define MAX77621_CTRL_HOS_CFG 0
|
#define MAX77621_CTRL_HOS_CFG 0
|
||||||
#define MAX77621_CTRL_POR_CFG 1
|
#define MAX77621_CTRL_POR_CFG 1
|
||||||
|
|
||||||
int max77620_regulator_get_status(u32 id);
|
int max77620_regulator_get_status(u32 id);
|
||||||
int max77620_regulator_config_fps(u32 id);
|
int max77620_regulator_config_fps(u32 id);
|
||||||
int max7762x_regulator_set_voltage(u32 id, u32 mv);
|
int max7762x_regulator_set_voltage(u32 id, u32 mv);
|
||||||
int max7762x_regulator_enable(u32 id, bool enable);
|
int max7762x_regulator_enable(u32 id, bool enable);
|
||||||
void max77620_config_gpio(u32 id, bool enable);
|
void max77620_config_gpio(u32 id, bool enable);
|
||||||
void max77620_config_default();
|
void max77620_config_default();
|
||||||
void max77620_low_battery_monitor_config(bool enable);
|
void max77620_low_battery_monitor_config(bool enable);
|
||||||
|
|||||||
@@ -81,7 +81,13 @@ bool regulator_5v_get_dev_enabled(u8 dev)
|
|||||||
void regulator_5v_batt_src_enable(bool enable)
|
void regulator_5v_batt_src_enable(bool enable)
|
||||||
{
|
{
|
||||||
if (enable && !batt_src)
|
if (enable && !batt_src)
|
||||||
|
{
|
||||||
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
|
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
|
||||||
|
batt_src = true;
|
||||||
|
}
|
||||||
else if (!enable && batt_src)
|
else if (!enable && batt_src)
|
||||||
|
{
|
||||||
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
|
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
|
||||||
|
batt_src = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
342
bdk/sec/se.c
342
bdk/sec/se.c
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018 CTCaer
|
* Copyright (c) 2018-2021 CTCaer
|
||||||
* Copyright (c) 2018 Atmosphère-NX
|
* Copyright (c) 2018 Atmosphère-NX
|
||||||
* Copyright (c) 2019-2020 shchmue
|
* Copyright (c) 2019-2021 shchmue
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -35,8 +35,8 @@ typedef struct _se_ll_t
|
|||||||
vu32 size;
|
vu32 size;
|
||||||
} se_ll_t;
|
} se_ll_t;
|
||||||
|
|
||||||
static u32 _se_rsa_mod_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT];
|
static u32 _se_rsa_mod_sizes[SE_RSA_KEYSLOT_COUNT];
|
||||||
static u32 _se_rsa_exp_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT];
|
static u32 _se_rsa_exp_sizes[SE_RSA_KEYSLOT_COUNT];
|
||||||
|
|
||||||
static void _gf256_mul_x(void *block)
|
static void _gf256_mul_x(void *block)
|
||||||
{
|
{
|
||||||
@@ -79,17 +79,17 @@ static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size)
|
|||||||
|
|
||||||
static void _se_ll_set(se_ll_t *dst, se_ll_t *src)
|
static void _se_ll_set(se_ll_t *dst, se_ll_t *src)
|
||||||
{
|
{
|
||||||
SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src;
|
SE(SE_IN_LL_ADDR_REG) = (u32)src;
|
||||||
SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst;
|
SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _se_wait()
|
static int _se_wait()
|
||||||
{
|
{
|
||||||
while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET)))
|
while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE))
|
||||||
;
|
;
|
||||||
if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) ||
|
if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
|
||||||
SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN ||
|
(SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
|
||||||
SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR)
|
SE(SE_ERR_STATUS_REG) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -114,12 +114,12 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
|
|||||||
|
|
||||||
_se_ll_set(ll_dst, ll_src);
|
_se_ll_set(ll_dst, ll_src);
|
||||||
|
|
||||||
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0);
|
SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
|
||||||
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET);
|
SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
|
||||||
|
|
||||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||||
|
|
||||||
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op);
|
SE(SE_OPERATION_REG) = op;
|
||||||
|
|
||||||
if (is_oneshot)
|
if (is_oneshot)
|
||||||
{
|
{
|
||||||
@@ -168,13 +168,13 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
|||||||
if (!src || !dst)
|
if (!src || !dst)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u8 *block = (u8 *)malloc(0x10);
|
u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE);
|
||||||
memset(block, 0, 0x10);
|
memset(block, 0, SE_AES_BLOCK_SIZE);
|
||||||
|
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||||
|
|
||||||
memcpy(block, src, src_size);
|
memcpy(block, src, src_size);
|
||||||
int res = _se_execute_oneshot(op, block, 0x10, block, 0x10);
|
int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
|
||||||
memcpy(dst, block, dst_size);
|
memcpy(dst, block, dst_size);
|
||||||
|
|
||||||
free(block);
|
free(block);
|
||||||
@@ -183,21 +183,21 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
|||||||
|
|
||||||
static void _se_aes_ctr_set(void *ctr)
|
static void _se_aes_ctr_set(void *ctr)
|
||||||
{
|
{
|
||||||
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
|
u32 data[SE_AES_IV_SIZE / 4];
|
||||||
memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE);
|
memcpy(data, ctr, SE_AES_IV_SIZE);
|
||||||
|
|
||||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++)
|
||||||
SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i];
|
SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void se_rsa_acc_ctrl(u32 rs, u32 flags)
|
void se_rsa_acc_ctrl(u32 rs, u32 flags)
|
||||||
{
|
{
|
||||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG)
|
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
|
||||||
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) =
|
SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
|
||||||
((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |
|
(((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
|
||||||
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG);
|
SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
|
||||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG)
|
if (flags & SE_RSA_KEY_LOCK_FLAG)
|
||||||
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs);
|
SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot
|
// se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot
|
||||||
@@ -206,15 +206,15 @@ void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32
|
|||||||
u32 *data = (u32 *)mod;
|
u32 *data = (u32 *)mod;
|
||||||
for (u32 i = 0; i < mod_size / 4; i++)
|
for (u32 i = 0; i < mod_size / 4; i++)
|
||||||
{
|
{
|
||||||
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i;
|
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
|
||||||
SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[mod_size / 4 - i - 1]);
|
SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[mod_size / 4 - i - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
data = (u32 *)exp;
|
data = (u32 *)exp;
|
||||||
for (u32 i = 0; i < exp_size / 4; i++)
|
for (u32 i = 0; i < exp_size / 4; i++)
|
||||||
{
|
{
|
||||||
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i;
|
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
|
||||||
SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[exp_size / 4 - i - 1]);
|
SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[exp_size / 4 - i - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_se_rsa_mod_sizes[ks] = mod_size;
|
_se_rsa_mod_sizes[ks] = mod_size;
|
||||||
@@ -224,15 +224,15 @@ void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32
|
|||||||
// se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot
|
// se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot
|
||||||
void se_rsa_key_clear(u32 ks)
|
void se_rsa_key_clear(u32 ks)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++)
|
for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
|
||||||
{
|
{
|
||||||
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i;
|
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i;
|
||||||
SE(SE_RSA_KEYTABLE_DATA) = 0;
|
SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
|
||||||
}
|
}
|
||||||
for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++)
|
for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++)
|
||||||
{
|
{
|
||||||
SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i;
|
SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i;
|
||||||
SE(SE_RSA_KEYTABLE_DATA) = 0;
|
SE(SE_RSA_KEYTABLE_DATA_REG) = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,22 +240,22 @@ void se_rsa_key_clear(u32 ks)
|
|||||||
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
|
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
u8 stack_buf[TEGRA_SE_RSA2048_DIGEST_SIZE];
|
u8 stack_buf[SE_RSA2048_DIGEST_SIZE];
|
||||||
|
|
||||||
for (u32 i = 0; i < src_size; i++)
|
for (u32 i = 0; i < src_size; i++)
|
||||||
stack_buf[i] = *((u8 *)src + src_size - i - 1);
|
stack_buf[i] = *((u8 *)src + src_size - i - 1);
|
||||||
|
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG);
|
||||||
SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks);
|
SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks);
|
||||||
SE(SE_RSA_KEY_SIZE_REG_OFFSET) = (_se_rsa_mod_sizes[ks] >> 6) - 1;
|
SE(SE_RSA_KEY_SIZE_REG) = (_se_rsa_mod_sizes[ks] >> 6) - 1;
|
||||||
SE(SE_RSA_EXP_SIZE_REG_OFFSET) = _se_rsa_exp_sizes[ks] >> 2;
|
SE(SE_RSA_EXP_SIZE_REG) = _se_rsa_exp_sizes[ks] >> 2;
|
||||||
|
|
||||||
res = _se_execute_oneshot(OP_START, NULL, 0, stack_buf, src_size);
|
res = _se_execute_oneshot(SE_OP_START, NULL, 0, stack_buf, src_size);
|
||||||
|
|
||||||
// Copy output hash.
|
// Copy output hash.
|
||||||
u32 *dst32 = (u32 *)dst;
|
u32 *dst32 = (u32 *)dst;
|
||||||
for (u32 i = 0; i < dst_size / 4; i++)
|
for (u32 i = 0; i < dst_size / 4; i++)
|
||||||
dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT + (i << 2)));
|
dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i << 2)));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -263,54 +263,54 @@ int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_siz
|
|||||||
void se_key_acc_ctrl(u32 ks, u32 flags)
|
void se_key_acc_ctrl(u32 ks, u32 flags)
|
||||||
{
|
{
|
||||||
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
|
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
|
||||||
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags;
|
SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags;
|
||||||
if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG)
|
if (flags & SE_KEY_LOCK_FLAG)
|
||||||
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks);
|
SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(ks);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 se_key_acc_ctrl_get(u32 ks)
|
u32 se_key_acc_ctrl_get(u32 ks)
|
||||||
{
|
{
|
||||||
return SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks);
|
return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void se_aes_key_set(u32 ks, const void *key, u32 size)
|
void se_aes_key_set(u32 ks, const void *key, u32 size)
|
||||||
{
|
{
|
||||||
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
|
u32 data[SE_AES_MAX_KEY_SIZE / 4];
|
||||||
memcpy(data, key, size);
|
memcpy(data, key, size);
|
||||||
|
|
||||||
for (u32 i = 0; i < (size / 4); i++)
|
for (u32 i = 0; i < (size / 4); i++)
|
||||||
{
|
{
|
||||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
|
||||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
|
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void se_aes_key_partial_set(u32 ks, u32 index, u32 data)
|
void se_aes_key_partial_set(u32 ks, u32 index, u32 data)
|
||||||
{
|
{
|
||||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | index;
|
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | index;
|
||||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data;
|
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void se_aes_iv_set(u32 ks, const void *iv)
|
void se_aes_iv_set(u32 ks, const void *iv)
|
||||||
{
|
{
|
||||||
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
|
u32 data[SE_AES_IV_SIZE / 4];
|
||||||
memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE);
|
memcpy(data, iv, SE_AES_IV_SIZE);
|
||||||
|
|
||||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
|
||||||
{
|
{
|
||||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
|
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
|
||||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
|
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void se_aes_key_get(u32 ks, void *key, u32 size)
|
void se_aes_key_get(u32 ks, void *key, u32 size)
|
||||||
{
|
{
|
||||||
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
|
u32 data[SE_AES_MAX_KEY_SIZE / 4];
|
||||||
|
|
||||||
for (u32 i = 0; i < (size / 4); i++)
|
for (u32 i = 0; i < (size / 4); i++)
|
||||||
{
|
{
|
||||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
|
||||||
data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET);
|
data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(key, data, size);
|
memcpy(key, data, size);
|
||||||
@@ -318,77 +318,77 @@ void se_aes_key_get(u32 ks, void *key, u32 size)
|
|||||||
|
|
||||||
void se_aes_key_clear(u32 ks)
|
void se_aes_key_clear(u32 ks)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < (TEGRA_SE_AES_MAX_KEY_SIZE / 4); i++)
|
for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / 4); i++)
|
||||||
{
|
{
|
||||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
|
||||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
|
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void se_aes_iv_clear(u32 ks)
|
void se_aes_iv_clear(u32 ks)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
|
||||||
{
|
{
|
||||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
|
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
|
||||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
|
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
|
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
|
||||||
{
|
{
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB);
|
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||||
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
|
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3);
|
||||||
|
|
||||||
return _se_execute_oneshot(OP_START, NULL, 0, input, 0x10);
|
return _se_execute_oneshot(SE_OP_START, NULL, 0, input, SE_KEY_128_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||||
{
|
{
|
||||||
if (enc)
|
if (enc)
|
||||||
{
|
{
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||||
}
|
}
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
|
||||||
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
|
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||||
{
|
{
|
||||||
if (enc)
|
if (enc)
|
||||||
{
|
{
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
|
||||||
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
|
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) |
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
|
||||||
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||||
}
|
}
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
|
||||||
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
|
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
|
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
|
||||||
{
|
{
|
||||||
return se_aes_crypt_ecb(ks, enc, dst, 0x10, src, 0x10);
|
return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
|
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
|
||||||
{
|
{
|
||||||
SE(SE_SPARE_0_REG_OFFSET) = 1;
|
SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
|
||||||
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1);
|
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1);
|
||||||
_se_aes_ctr_set(ctr);
|
_se_aes_ctr_set(ctr);
|
||||||
|
|
||||||
u32 src_size_aligned = src_size & 0xFFFFFFF0;
|
u32 src_size_aligned = src_size & 0xFFFFFFF0;
|
||||||
@@ -396,13 +396,13 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
|
|||||||
|
|
||||||
if (src_size_aligned)
|
if (src_size_aligned)
|
||||||
{
|
{
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
|
||||||
if (!_se_execute_oneshot(OP_START, dst, dst_size, src, src_size_aligned))
|
if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src_size - src_size_aligned && src_size_aligned < dst_size)
|
if (src_size - src_size_aligned && src_size_aligned < dst_size)
|
||||||
return _se_execute_one_block(OP_START, dst + src_size_aligned,
|
return _se_execute_one_block(SE_OP_START, dst + src_size_aligned,
|
||||||
MIN(src_size_delta, dst_size - src_size_aligned),
|
MIN(src_size_delta, dst_size - src_size_aligned),
|
||||||
src + src_size_aligned, src_size_delta);
|
src + src_size_aligned, src_size_delta);
|
||||||
|
|
||||||
@@ -419,15 +419,15 @@ int se_initialize_rng()
|
|||||||
|
|
||||||
u8 *output_buf = (u8 *)malloc(0x10);
|
u8 *output_buf = (u8 *)malloc(0x10);
|
||||||
|
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
|
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
|
||||||
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 70001;
|
SE(SE_RNG_RESEED_INTERVAL_REG) = 70001;
|
||||||
SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) |
|
SE(SE_RNG_SRC_CONFIG_REG) = SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) |
|
||||||
SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
|
SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
|
||||||
|
|
||||||
int res =_se_execute_oneshot(OP_START, output_buf, 0x10, NULL, 0);
|
int res =_se_execute_oneshot(SE_OP_START, output_buf, 0x10, NULL, 0);
|
||||||
|
|
||||||
free(output_buf);
|
free(output_buf);
|
||||||
if (res)
|
if (res)
|
||||||
@@ -437,35 +437,35 @@ int se_initialize_rng()
|
|||||||
|
|
||||||
int se_generate_random(void *dst, u32 size)
|
int se_generate_random(void *dst, u32 size)
|
||||||
{
|
{
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
|
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
|
||||||
|
|
||||||
u32 num_blocks = size >> 4;
|
u32 num_blocks = size >> 4;
|
||||||
u32 aligned_size = num_blocks << 4;
|
u32 aligned_size = num_blocks << 4;
|
||||||
if (num_blocks)
|
if (num_blocks)
|
||||||
{
|
{
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 1;
|
||||||
if (!_se_execute_oneshot(OP_START, dst, aligned_size, NULL, 0))
|
if (!_se_execute_oneshot(SE_OP_START, dst, aligned_size, NULL, 0))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (size > aligned_size)
|
if (size > aligned_size)
|
||||||
return _se_execute_one_block(OP_START, dst + aligned_size, size - aligned_size, NULL, 0);
|
return _se_execute_one_block(SE_OP_START, dst + aligned_size, size - aligned_size, NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int se_generate_random_key(u32 ks_dst, u32 ks_src)
|
int se_generate_random_key(u32 ks_dst, u32 ks_src)
|
||||||
{
|
{
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
|
||||||
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
|
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_MODE(MODE_NORMAL) | SE_RNG_CONFIG_SRC(SRC_ENTROPY);
|
||||||
|
|
||||||
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
|
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst);
|
||||||
if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0))
|
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
|
||||||
return 0;
|
return 0;
|
||||||
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
|
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
|
||||||
if (!_se_execute_oneshot(OP_START, NULL, 0, NULL, 0))
|
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -544,8 +544,8 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
|
|||||||
if (src_size & 0xF)
|
if (src_size & 0xF)
|
||||||
_gf256_mul_x(key);
|
_gf256_mul_x(key);
|
||||||
|
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) |
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
|
||||||
SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) |
|
SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) |
|
||||||
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
||||||
se_aes_iv_clear(ks);
|
se_aes_iv_clear(ks);
|
||||||
@@ -553,10 +553,10 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
|
|||||||
u32 num_blocks = (src_size + 0xf) >> 4;
|
u32 num_blocks = (src_size + 0xf) >> 4;
|
||||||
if (num_blocks > 1)
|
if (num_blocks > 1)
|
||||||
{
|
{
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = num_blocks - 2;
|
||||||
if (!_se_execute_oneshot(OP_START, NULL, 0, src, src_size))
|
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, src_size))
|
||||||
goto out;
|
goto out;
|
||||||
SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
|
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src_size & 0xf)
|
if (src_size & 0xf)
|
||||||
@@ -572,12 +572,12 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
|
|||||||
for (u32 i = 0; i < 0x10; i++)
|
for (u32 i = 0; i < 0x10; i++)
|
||||||
last_block[i] ^= key[i];
|
last_block[i] ^= key[i];
|
||||||
|
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 0;
|
||||||
res = _se_execute_oneshot(OP_START, NULL, 0, last_block, 0x10);
|
res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, 0x10);
|
||||||
|
|
||||||
u32 *dst32 = (u32 *)dst;
|
u32 *dst32 = (u32 *)dst;
|
||||||
for (u32 i = 0; i < (dst_size >> 2); i++)
|
for (u32 i = 0; i < (dst_size >> 2); i++)
|
||||||
dst32[i] = SE(SE_HASH_RESULT_REG_OFFSET + (i << 2));
|
dst32[i] = SE(SE_HASH_RESULT_REG + (i << 2));
|
||||||
|
|
||||||
out:;
|
out:;
|
||||||
free(key);
|
free(key);
|
||||||
@@ -588,62 +588,62 @@ out:;
|
|||||||
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
|
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
|
u32 hash32[SE_SHA_256_SIZE / 4];
|
||||||
|
|
||||||
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
|
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
|
||||||
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
|
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Setup config for SHA256.
|
// Setup config for SHA256.
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||||
SE(SE_SHA_CONFIG_REG_OFFSET) = sha_cfg;
|
SE(SE_SHA_CONFIG_REG) = sha_cfg;
|
||||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||||
|
|
||||||
// Set total size to current buffer size if empty.
|
// Set total size to current buffer size if empty.
|
||||||
if (!total_size)
|
if (!total_size)
|
||||||
total_size = src_size;
|
total_size = src_size;
|
||||||
|
|
||||||
// Set total size: BITS(src_size), up to 2 EB.
|
// Set total size: BITS(src_size), up to 2 EB.
|
||||||
SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(total_size << 3);
|
SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
|
||||||
SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29);
|
SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
|
||||||
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0;
|
SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
|
||||||
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0;
|
SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
|
||||||
|
|
||||||
// Set size left to hash.
|
// Set size left to hash.
|
||||||
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3);
|
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
|
||||||
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29);
|
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
|
||||||
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0;
|
SE(SE_SHA_MSG_LEFT_2_REG) = 0;
|
||||||
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0;
|
SE(SE_SHA_MSG_LEFT_3_REG) = 0;
|
||||||
|
|
||||||
// If we hash in chunks, copy over the intermediate.
|
// If we hash in chunks, copy over the intermediate.
|
||||||
if (sha_cfg == SHA_CONTINUE && msg_left)
|
if (sha_cfg == SHA_CONTINUE && msg_left)
|
||||||
{
|
{
|
||||||
// Restore message left to process.
|
// Restore message left to process.
|
||||||
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0];
|
SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
|
||||||
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1];
|
SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
|
||||||
|
|
||||||
// Restore hash reg.
|
// Restore hash reg.
|
||||||
memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE);
|
memcpy(hash32, hash, SE_SHA_256_SIZE);
|
||||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||||
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]);
|
SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger the operation.
|
// Trigger the operation.
|
||||||
res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot);
|
res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
|
||||||
|
|
||||||
if (is_oneshot)
|
if (is_oneshot)
|
||||||
{
|
{
|
||||||
// Backup message left.
|
// Backup message left.
|
||||||
if (msg_left)
|
if (msg_left)
|
||||||
{
|
{
|
||||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
|
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
|
||||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
|
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy output hash.
|
// Copy output hash.
|
||||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
|
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
|
||||||
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
|
memcpy(hash, hash32, SE_SHA_256_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@@ -656,20 +656,20 @@ int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size)
|
|||||||
|
|
||||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
int se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
||||||
{
|
{
|
||||||
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
|
u32 hash32[SE_SHA_256_SIZE / 4];
|
||||||
int res = _se_execute_finalize();
|
int res = _se_execute_finalize();
|
||||||
|
|
||||||
// Backup message left.
|
// Backup message left.
|
||||||
if (msg_left)
|
if (msg_left)
|
||||||
{
|
{
|
||||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
|
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
|
||||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
|
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy output hash.
|
// Copy output hash.
|
||||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
|
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i << 2)));
|
||||||
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
|
memcpy(hash, hash32, SE_SHA_256_SIZE);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -793,43 +793,43 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
|||||||
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
|
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
|
||||||
|
|
||||||
// Set Secure Random Key.
|
// Set Secure Random Key.
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
|
||||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED);
|
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED);
|
||||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||||
_se_execute_oneshot(OP_START, NULL, 0, NULL, 0);
|
_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0);
|
||||||
|
|
||||||
// Save AES keys.
|
// Save AES keys.
|
||||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||||
|
|
||||||
for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++)
|
for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++)
|
||||||
{
|
{
|
||||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
|
||||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3);
|
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
|
||||||
|
|
||||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||||
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
|
||||||
memcpy(keys + i * keysize, aligned_buf, 0x10);
|
memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
|
||||||
|
|
||||||
if (keysize > 0x10)
|
if (keysize > SE_KEY_128_SIZE)
|
||||||
{
|
{
|
||||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
|
||||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7);
|
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
|
||||||
|
|
||||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||||
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
|
||||||
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10);
|
memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save SRK to PMC secure scratches.
|
// Save SRK to PMC secure scratches.
|
||||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK);
|
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
|
||||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||||
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||||
|
|
||||||
// End context save.
|
// End context save.
|
||||||
SE(SE_CONFIG_REG_OFFSET) = 0;
|
SE(SE_CONFIG_REG) = 0;
|
||||||
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||||
|
|
||||||
// Get SRK.
|
// Get SRK.
|
||||||
u32 srk[4];
|
u32 srk[4];
|
||||||
@@ -840,7 +840,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
|||||||
|
|
||||||
// Decrypt context.
|
// Decrypt context.
|
||||||
se_aes_key_clear(3);
|
se_aes_key_clear(3);
|
||||||
se_aes_key_set(3, srk, 0x10);
|
se_aes_key_set(3, srk, SE_KEY_128_SIZE);
|
||||||
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize);
|
se_aes_crypt_cbc(3, 0, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
|
||||||
se_aes_key_clear(3);
|
se_aes_key_clear(3);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
|
* Copyright (c) 2019-2021 CTCaer
|
||||||
|
* Copyright (c) 2019-2021 shchmue
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -25,6 +27,7 @@ void se_rsa_key_clear(u32 ks);
|
|||||||
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
|
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||||
void se_key_acc_ctrl(u32 ks, u32 flags);
|
void se_key_acc_ctrl(u32 ks, u32 flags);
|
||||||
u32 se_key_acc_ctrl_get(u32 ks);
|
u32 se_key_acc_ctrl_get(u32 ks);
|
||||||
|
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
|
||||||
void se_aes_key_set(u32 ks, const void *key, u32 size);
|
void se_aes_key_set(u32 ks, const void *key, u32 size);
|
||||||
void se_aes_iv_set(u32 ks, const void *iv);
|
void se_aes_iv_set(u32 ks, const void *iv);
|
||||||
void se_aes_key_partial_set(u32 ks, u32 index, u32 data);
|
void se_aes_key_partial_set(u32 ks, u32 index, u32 data);
|
||||||
@@ -35,10 +38,10 @@ int se_initialize_rng();
|
|||||||
int se_generate_random(void *dst, u32 size);
|
int se_generate_random(void *dst, u32 size);
|
||||||
int se_generate_random_key(u32 ks_dst, u32 ks_src);
|
int se_generate_random_key(u32 ks_dst, u32 ks_src);
|
||||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
|
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
|
||||||
|
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||||
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
|
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
|
||||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
|
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
|
||||||
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
|
||||||
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size);
|
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size);
|
||||||
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs);
|
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, const void *src, u32 sec_size, u32 num_secs);
|
||||||
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
|
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||||
@@ -47,6 +50,5 @@ int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
|
|||||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
|
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
|
||||||
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
|
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size);
|
||||||
u32 se_rsa_oaep_decode(void *dst, u32 dst_size, const void *label_digest, u32 label_digest_size, u8 *buf, u32 buf_size);
|
u32 se_rsa_oaep_decode(void *dst, u32 dst_size, const void *label_digest, u32 label_digest_size, u8 *buf, u32 buf_size);
|
||||||
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,400 +1,323 @@
|
|||||||
/*
|
/*
|
||||||
* Driver for Tegra Security Engine
|
* Copyright (c) 2018 naehrwert
|
||||||
*
|
* Copyright (c) 2018-2021 CTCaer
|
||||||
* Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved.
|
*
|
||||||
*
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* under the terms and conditions of the GNU General Public License,
|
||||||
* it under the terms of the GNU General Public License as published by
|
* version 2, as published by the Free Software Foundation.
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
*
|
||||||
* (at your option) any later version.
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
*
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* more details.
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
*
|
||||||
* more details.
|
* You should have received a copy of the GNU General Public License
|
||||||
*
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* You should have received a copy of the GNU General Public License along
|
*/
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _CRYPTO_TEGRA_SE_H
|
#ifndef _SE_T210_H
|
||||||
#define _CRYPTO_TEGRA_SE_H
|
#define _SE_T210_H
|
||||||
|
|
||||||
#include <utils/types.h>
|
#include <utils/types.h>
|
||||||
|
|
||||||
#define TEGRA_SE_CRA_PRIORITY 300
|
#define SE_CRYPTO_QUEUE_LENGTH 50
|
||||||
#define TEGRA_SE_COMPOSITE_PRIORITY 400
|
#define SE_MAX_SRC_SG_COUNT 50
|
||||||
#define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50
|
#define SE_MAX_DST_SG_COUNT 50
|
||||||
#define SE_MAX_SRC_SG_COUNT 50
|
|
||||||
#define SE_MAX_DST_SG_COUNT 50
|
|
||||||
|
|
||||||
#define TEGRA_SE_KEYSLOT_COUNT 16
|
#define SE_AES_KEYSLOT_COUNT 16
|
||||||
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
|
#define SE_RSA_KEYSLOT_COUNT 2
|
||||||
|
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
|
||||||
|
|
||||||
|
#define SE_AES_BLOCK_SIZE 16
|
||||||
|
#define SE_AES_IV_SIZE 16
|
||||||
|
#define SE_AES_MIN_KEY_SIZE 16
|
||||||
|
#define SE_AES_MAX_KEY_SIZE 32
|
||||||
|
#define SE_KEY_128_SIZE 16
|
||||||
|
#define SE_KEY_192_SIZE 24
|
||||||
|
#define SE_KEY_256_SIZE 32
|
||||||
|
#define SE_SHA_192_SIZE 24
|
||||||
|
#define SE_SHA_256_SIZE 32
|
||||||
|
#define SE_SHA_384_SIZE 48
|
||||||
|
#define SE_SHA_512_SIZE 64
|
||||||
|
#define SE_RNG_IV_SIZE 16
|
||||||
|
#define SE_RNG_DT_SIZE 16
|
||||||
|
#define SE_RNG_KEY_SIZE 16
|
||||||
|
#define SE_RNG_SEED_SIZE (SE_RNG_IV_SIZE + SE_RNG_KEY_SIZE + SE_RNG_DT_SIZE)
|
||||||
|
|
||||||
|
#define SE_AES_CMAC_DIGEST_SIZE 16
|
||||||
|
#define SE_RSA512_DIGEST_SIZE 64
|
||||||
|
#define SE_RSA1024_DIGEST_SIZE 128
|
||||||
|
#define SE_RSA1536_DIGEST_SIZE 192
|
||||||
|
#define SE_RSA2048_DIGEST_SIZE 256
|
||||||
|
|
||||||
/* SE register definitions */
|
/* SE register definitions */
|
||||||
#define SE_SECURITY_0 0x000
|
#define SE_SE_SECURITY_REG 0x000
|
||||||
#define SE_KEY_SCHED_READ_SHIFT 3
|
#define SE_HARD_SETTING BIT(0)
|
||||||
|
#define SE_ENG_DIS BIT(1)
|
||||||
|
#define SE_PERKEY_SETTING BIT(2)
|
||||||
|
#define SE_SOFT_SETTING BIT(16)
|
||||||
|
|
||||||
#define SE_TZRAM_SECURITY_0 0x004
|
#define SE_TZRAM_SECURITY_REG 0x004
|
||||||
|
#define SE_TZRAM_HARD_SETTING BIT(0)
|
||||||
|
#define SE_TZRAM_ENG_DIS BIT(1)
|
||||||
|
|
||||||
#define SE_CONFIG_REG_OFFSET 0x014
|
#define SE_OPERATION_REG 0x008
|
||||||
#define SE_CONFIG_ENC_ALG_SHIFT 12
|
#define SE_OP_ABORT 0
|
||||||
#define SE_CONFIG_DEC_ALG_SHIFT 8
|
#define SE_OP_START 1
|
||||||
#define ALG_AES_ENC 1
|
#define SE_OP_RESTART_OUT 2
|
||||||
#define ALG_RNG 2
|
#define SE_OP_CTX_SAVE 3
|
||||||
#define ALG_SHA 3
|
#define SE_OP_RESTART_IN 4
|
||||||
#define ALG_RSA 4
|
|
||||||
#define ALG_NOP 0
|
|
||||||
#define ALG_AES_DEC 1
|
|
||||||
#define SE_CONFIG_ENC_ALG(x) ((x) << SE_CONFIG_ENC_ALG_SHIFT)
|
|
||||||
#define SE_CONFIG_DEC_ALG(x) ((x) << SE_CONFIG_DEC_ALG_SHIFT)
|
|
||||||
#define SE_CONFIG_DST_SHIFT 2
|
|
||||||
#define DST_MEMORY 0
|
|
||||||
#define DST_HASHREG 1
|
|
||||||
#define DST_KEYTAB 2
|
|
||||||
#define DST_SRK 3
|
|
||||||
#define DST_RSAREG 4
|
|
||||||
#define SE_CONFIG_DST(x) ((x) << SE_CONFIG_DST_SHIFT)
|
|
||||||
#define SE_CONFIG_ENC_MODE_SHIFT 24
|
|
||||||
#define SE_CONFIG_DEC_MODE_SHIFT 16
|
|
||||||
#define MODE_KEY128 0
|
|
||||||
#define MODE_KEY192 1
|
|
||||||
#define MODE_KEY256 2
|
|
||||||
#define MODE_SHA1 0
|
|
||||||
#define MODE_SHA224 4
|
|
||||||
#define MODE_SHA256 5
|
|
||||||
#define MODE_SHA384 6
|
|
||||||
#define MODE_SHA512 7
|
|
||||||
#define SE_CONFIG_ENC_MODE(x) ((x) << SE_CONFIG_ENC_MODE_SHIFT)
|
|
||||||
#define SE_CONFIG_DEC_MODE(x) ((x) << SE_CONFIG_DEC_MODE_SHIFT)
|
|
||||||
|
|
||||||
#define SE_RNG_CONFIG_REG_OFFSET 0x340
|
#define SE_INT_ENABLE_REG 0x00C
|
||||||
#define RNG_MODE_SHIFT 0
|
#define SE_INT_STATUS_REG 0x010
|
||||||
#define RNG_MODE_NORMAL 0
|
#define SE_INT_IN_LL_BUF_RD BIT(0)
|
||||||
#define RNG_MODE_FORCE_INSTANTION 1
|
#define SE_INT_IN_DONE BIT(1)
|
||||||
#define RNG_MODE_FORCE_RESEED 2
|
#define SE_INT_OUT_LL_BUF_WR BIT(2)
|
||||||
#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT)
|
#define SE_INT_OUT_DONE BIT(3)
|
||||||
#define RNG_SRC_SHIFT 2
|
#define SE_INT_OP_DONE BIT(4)
|
||||||
#define RNG_SRC_NONE 0
|
#define SE_INT_RESEED_NEEDED BIT(5)
|
||||||
#define RNG_SRC_ENTROPY 1
|
#define SE_INT_ERR_STAT BIT(16)
|
||||||
#define RNG_SRC_LFSR 2
|
|
||||||
#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT)
|
|
||||||
|
|
||||||
#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344
|
#define SE_CONFIG_REG 0x014
|
||||||
#define RNG_SRC_RO_ENT_SHIFT 1
|
#define DST_MEMORY 0
|
||||||
#define RNG_SRC_RO_ENT_ENABLE 1
|
#define DST_HASHREG 1
|
||||||
#define RNG_SRC_RO_ENT_DISABLE 0
|
#define DST_KEYTABLE 2
|
||||||
#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT)
|
#define DST_SRK 3
|
||||||
#define RNG_SRC_RO_ENT_LOCK_SHIFT 0
|
#define DST_RSAREG 4
|
||||||
#define RNG_SRC_RO_ENT_LOCK_ENABLE 1
|
#define SE_CONFIG_DST(x) ((x) << 2)
|
||||||
#define RNG_SRC_RO_ENT_LOCK_DISABLE 0
|
#define ALG_NOP 0
|
||||||
#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT)
|
#define ALG_AES_DEC 1
|
||||||
|
#define SE_CONFIG_DEC_ALG(x) ((x) << 8)
|
||||||
|
#define ALG_NOP 0
|
||||||
|
#define ALG_AES_ENC 1
|
||||||
|
#define ALG_RNG 2
|
||||||
|
#define ALG_SHA 3
|
||||||
|
#define ALG_RSA 4
|
||||||
|
#define SE_CONFIG_ENC_ALG(x) ((x) << 12)
|
||||||
|
#define MODE_KEY128 0
|
||||||
|
#define MODE_KEY192 1
|
||||||
|
#define MODE_KEY256 2
|
||||||
|
#define MODE_SHA1 0
|
||||||
|
#define MODE_SHA224 4
|
||||||
|
#define MODE_SHA256 5
|
||||||
|
#define MODE_SHA384 6
|
||||||
|
#define MODE_SHA512 7
|
||||||
|
#define SE_CONFIG_DEC_MODE(x) ((x) << 16)
|
||||||
|
#define SE_CONFIG_ENC_MODE(x) ((x) << 24)
|
||||||
|
|
||||||
#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348
|
#define SE_IN_LL_ADDR_REG 0x018
|
||||||
|
#define SE_IN_CUR_BYTE_ADDR_REG 0x01C
|
||||||
|
#define SE_IN_CUR_LL_ID_REG 0x020
|
||||||
|
#define SE_OUT_LL_ADDR_REG 0x024
|
||||||
|
#define SE_OUT_CUR_BYTE_ADDR_REG 0x028
|
||||||
|
#define SE_OUT_CUR_LL_ID_REG 0x02C
|
||||||
|
|
||||||
#define SE_KEYTABLE_REG_OFFSET 0x31c
|
#define SE_HASH_RESULT_REG 0x030
|
||||||
#define SE_KEYTABLE_SLOT_SHIFT 4
|
#define SE_HASH_RESULT_REG_COUNT 16
|
||||||
#define SE_KEYTABLE_SLOT(x) ((x) << SE_KEYTABLE_SLOT_SHIFT)
|
|
||||||
#define SE_KEYTABLE_QUAD_SHIFT 2
|
|
||||||
#define QUAD_KEYS_128 0
|
|
||||||
#define QUAD_KEYS_192 1
|
|
||||||
#define QUAD_KEYS_256 1
|
|
||||||
#define QUAD_ORG_IV 2
|
|
||||||
#define QUAD_UPDTD_IV 3
|
|
||||||
#define SE_KEYTABLE_QUAD(x) ((x) << SE_KEYTABLE_QUAD_SHIFT)
|
|
||||||
#define SE_KEYTABLE_OP_TYPE_SHIFT 9
|
|
||||||
#define OP_READ 0
|
|
||||||
#define OP_WRITE 1
|
|
||||||
#define SE_KEYTABLE_OP_TYPE(x) ((x) << SE_KEYTABLE_OP_TYPE_SHIFT)
|
|
||||||
#define SE_KEYTABLE_TABLE_SEL_SHIFT 8
|
|
||||||
#define TABLE_KEYIV 0
|
|
||||||
#define TABLE_SCHEDULE 1
|
|
||||||
#define SE_KEYTABLE_TABLE_SEL(x) ((x) << SE_KEYTABLE_TABLE_SEL_SHIFT)
|
|
||||||
#define SE_KEYTABLE_PKT_SHIFT 0
|
|
||||||
#define SE_KEYTABLE_PKT(x) ((x) << SE_KEYTABLE_PKT_SHIFT)
|
|
||||||
|
|
||||||
#define SE_OP_DONE_SHIFT 4
|
#define SE_CONTEXT_SAVE_CONFIG_REG 0x070
|
||||||
#define OP_DONE 1
|
#define KEYS_0_3 0
|
||||||
#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT))
|
#define KEYS_4_7 1
|
||||||
|
#define ORIGINAL_IV 2
|
||||||
|
#define UPDATED_IV 3
|
||||||
|
#define SE_CONTEXT_AES_WORD_QUAD(x) ((x) << 0)
|
||||||
|
#define SE_CONTEXT_AES_KEY_INDEX(x) ((x) << 8)
|
||||||
|
#define KEYS_0_3 0
|
||||||
|
#define KEYS_4_7 1
|
||||||
|
#define KEYS_8_11 2
|
||||||
|
#define KEYS_12_15 3
|
||||||
|
#define SE_CONTEXT_RSA_WORD_QUAD(x) ((x) << 12)
|
||||||
|
#define SLOT0_EXPONENT 0
|
||||||
|
#define SLOT0_MODULUS 1
|
||||||
|
#define SLOT1_EXPONENT 2
|
||||||
|
#define SLOT1_MODULUS 3
|
||||||
|
#define SE_CONTEXT_RSA_KEY_INDEX(x) ((x) << 16)
|
||||||
|
#define STICKY_0_3 0
|
||||||
|
#define STICKY_4_7 1
|
||||||
|
#define SE_CONTEXT_STICKY_WORD_QUAD(x) ((x) << 24)
|
||||||
|
#define STICKY_BITS 0
|
||||||
|
#define RSA_KEYTABLE 1
|
||||||
|
#define AES_KEYTABLE 2
|
||||||
|
#define MEM 4
|
||||||
|
#define SRK 6
|
||||||
|
#define SE_CONTEXT_SRC(x) ((x) << 29)
|
||||||
|
|
||||||
#define SE_CRYPTO_LAST_BLOCK 0x080
|
#define SE_CTX_SAVE_AUTO_T210B01_REG 0x074
|
||||||
|
#define SE_CTX_SAVE_AUTO_ENABLE BIT(0)
|
||||||
|
#define SE_CTX_SAVE_AUTO_LOCK BIT(8)
|
||||||
|
#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
|
||||||
|
|
||||||
#define SE_CRYPTO_REG_OFFSET 0x304
|
#define SE_CRYPTO_LAST_BLOCK 0x080
|
||||||
#define SE_CRYPTO_HASH_SHIFT 0
|
|
||||||
#define HASH_DISABLE 0
|
|
||||||
#define HASH_ENABLE 1
|
|
||||||
#define SE_CRYPTO_HASH(x) ((x) << SE_CRYPTO_HASH_SHIFT)
|
|
||||||
#define SE_CRYPTO_XOR_POS_SHIFT 1
|
|
||||||
#define XOR_BYPASS 0
|
|
||||||
#define XOR_TOP 2
|
|
||||||
#define XOR_BOTTOM 3
|
|
||||||
#define SE_CRYPTO_XOR_POS(x) ((x) << SE_CRYPTO_XOR_POS_SHIFT)
|
|
||||||
#define SE_CRYPTO_INPUT_SEL_SHIFT 3
|
|
||||||
#define INPUT_AHB 0
|
|
||||||
#define INPUT_RANDOM 1
|
|
||||||
#define INPUT_AESOUT 2
|
|
||||||
#define INPUT_LNR_CTR 3
|
|
||||||
#define SE_CRYPTO_INPUT_SEL(x) ((x) << SE_CRYPTO_INPUT_SEL_SHIFT)
|
|
||||||
#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5
|
|
||||||
#define VCTRAM_AHB 0
|
|
||||||
#define VCTRAM_AESOUT 2
|
|
||||||
#define VCTRAM_PREVAHB 3
|
|
||||||
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << SE_CRYPTO_VCTRAM_SEL_SHIFT)
|
|
||||||
#define SE_CRYPTO_IV_SEL_SHIFT 7
|
|
||||||
#define IV_ORIGINAL 0
|
|
||||||
#define IV_UPDATED 1
|
|
||||||
#define SE_CRYPTO_IV_SEL(x) ((x) << SE_CRYPTO_IV_SEL_SHIFT)
|
|
||||||
#define SE_CRYPTO_CORE_SEL_SHIFT 8
|
|
||||||
#define CORE_DECRYPT 0
|
|
||||||
#define CORE_ENCRYPT 1
|
|
||||||
#define SE_CRYPTO_CORE_SEL(x) ((x) << SE_CRYPTO_CORE_SEL_SHIFT)
|
|
||||||
#define SE_CRYPTO_CTR_VAL_SHIFT 11
|
|
||||||
#define SE_CRYPTO_CTR_VAL(x) ((x) << SE_CRYPTO_CTR_VAL_SHIFT)
|
|
||||||
#define SE_CRYPTO_KEY_INDEX_SHIFT 24
|
|
||||||
#define SE_CRYPTO_KEY_INDEX(x) ((x) << SE_CRYPTO_KEY_INDEX_SHIFT)
|
|
||||||
#define SE_CRYPTO_CTR_CNTN_SHIFT 11
|
|
||||||
#define SE_CRYPTO_CTR_CNTN(x) ((x) << SE_CRYPTO_CTR_CNTN_SHIFT)
|
|
||||||
|
|
||||||
#define SE_CRYPTO_CTR_REG_COUNT 4
|
#define SE_SHA_CONFIG_REG 0x200
|
||||||
#define SE_CRYPTO_CTR_REG_OFFSET 0x308
|
|
||||||
|
|
||||||
#define SE_OPERATION_REG_OFFSET 0x008
|
|
||||||
#define SE_OPERATION_SHIFT 0
|
|
||||||
#define OP_ABORT 0
|
|
||||||
#define OP_START 1
|
|
||||||
#define OP_RESTART 2
|
|
||||||
#define OP_CTX_SAVE 3
|
|
||||||
#define OP_RESTART_IN 4
|
|
||||||
#define SE_OPERATION(x) ((x) << SE_OPERATION_SHIFT)
|
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_CONFIG_REG_OFFSET 0x070
|
|
||||||
#define SE_CONTEXT_SAVE_WORD_QUAD_SHIFT 0
|
|
||||||
#define KEYS_0_3 0
|
|
||||||
#define KEYS_4_7 1
|
|
||||||
#define ORIG_IV 2
|
|
||||||
#define UPD_IV 3
|
|
||||||
#define SE_CONTEXT_SAVE_WORD_QUAD(x) ((x) << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT)
|
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_KEY_INDEX_SHIFT 8
|
|
||||||
#define SE_CONTEXT_SAVE_KEY_INDEX(x) ((x) << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT)
|
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT 24
|
|
||||||
#define STICKY_0_3 0
|
|
||||||
#define STICKY_4_7 1
|
|
||||||
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD(x) \
|
|
||||||
((x) << SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT)
|
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_SRC_SHIFT 29
|
|
||||||
#define STICKY_BITS 0
|
|
||||||
#define KEYTABLE 2
|
|
||||||
#define MEM 4
|
|
||||||
#define SRK 6
|
|
||||||
|
|
||||||
#define RSA_KEYTABLE 1
|
|
||||||
#define AES_KEYTABLE 2
|
|
||||||
#define SE_CONTEXT_SAVE_SRC(x) ((x) << SE_CONTEXT_SAVE_SRC_SHIFT)
|
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT 16
|
|
||||||
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX(x) \
|
|
||||||
((x) << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT)
|
|
||||||
|
|
||||||
#define SE_CONTEXT_RSA_WORD_QUAD_SHIFT 12
|
|
||||||
#define SE_CONTEXT_RSA_WORD_QUAD(x) \
|
|
||||||
((x) << SE_CONTEXT_RSA_WORD_QUAD_SHIFT)
|
|
||||||
|
|
||||||
#define SE_CTX_SAVE_AUTO 0x074
|
|
||||||
#define CTX_SAVE_AUTO_ENABLE BIT(0)
|
|
||||||
#define CTX_SAVE_AUTO_LOCK BIT(8)
|
|
||||||
#define CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
|
|
||||||
|
|
||||||
#define SE_INT_ENABLE_REG_OFFSET 0x00c
|
|
||||||
#define SE_INT_STATUS_REG_OFFSET 0x010
|
|
||||||
#define INT_DISABLE 0
|
|
||||||
#define INT_ENABLE 1
|
|
||||||
#define INT_UNSET 0
|
|
||||||
#define INT_SET 1
|
|
||||||
#define SE_INT_OP_DONE_SHIFT 4
|
|
||||||
#define SE_INT_OP_DONE(x) ((x) << SE_INT_OP_DONE_SHIFT)
|
|
||||||
#define SE_INT_ERROR_SHIFT 16
|
|
||||||
#define SE_INT_ERROR(x) ((x) << SE_INT_ERROR_SHIFT)
|
|
||||||
|
|
||||||
#define SE_STATUS_0 0x800
|
|
||||||
#define SE_STATUS_0_STATE_WAIT_IN 3
|
|
||||||
|
|
||||||
#define SE_ERR_STATUS_0 0x804
|
|
||||||
#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0
|
|
||||||
|
|
||||||
#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330
|
|
||||||
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0
|
|
||||||
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \
|
|
||||||
((x) << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT)
|
|
||||||
|
|
||||||
#define SE_KEY_INDEX_SHIFT 8
|
|
||||||
#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) ((x) << SE_KEY_INDEX_SHIFT)
|
|
||||||
|
|
||||||
#define SE_IN_LL_ADDR_REG_OFFSET 0x018
|
|
||||||
#define SE_OUT_LL_ADDR_REG_OFFSET 0x024
|
|
||||||
|
|
||||||
#define SE_KEYTABLE_DATA0_REG_OFFSET 0x320
|
|
||||||
#define SE_KEYTABLE_REG_MAX_DATA 16
|
|
||||||
|
|
||||||
#define SE_BLOCK_COUNT_REG_OFFSET 0x318
|
|
||||||
|
|
||||||
#define SE_SPARE_0_REG_OFFSET 0x80c
|
|
||||||
|
|
||||||
#define SE_SHA_CONFIG_REG_OFFSET 0x200
|
|
||||||
#define SHA_CONTINUE 0
|
#define SHA_CONTINUE 0
|
||||||
#define SHA_INIT_HASH 1
|
#define SHA_INIT_HASH 1
|
||||||
|
|
||||||
#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204
|
#define SE_SHA_MSG_LENGTH_0_REG 0x204
|
||||||
#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208
|
#define SE_SHA_MSG_LENGTH_1_REG 0x208
|
||||||
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C
|
#define SE_SHA_MSG_LENGTH_2_REG 0x20C
|
||||||
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210
|
#define SE_SHA_MSG_LENGTH_3_REG 0x210
|
||||||
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214
|
#define SE_SHA_MSG_LEFT_0_REG 0x214
|
||||||
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218
|
#define SE_SHA_MSG_LEFT_1_REG 0x218
|
||||||
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C
|
#define SE_SHA_MSG_LEFT_2_REG 0x21C
|
||||||
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220
|
#define SE_SHA_MSG_LEFT_3_REG 0x220
|
||||||
|
|
||||||
#define SE_HASH_RESULT_REG_COUNT 16
|
#define SE_CRYPTO_SECURITY_PERKEY_REG 0x280
|
||||||
#define SE_HASH_RESULT_REG_OFFSET 0x030
|
#define SE_KEY_LOCK_FLAG 0x80
|
||||||
#define TEGRA_SE_KEY_256_SIZE 32
|
#define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284
|
||||||
#define TEGRA_SE_KEY_192_SIZE 24
|
#define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16
|
||||||
#define TEGRA_SE_KEY_128_SIZE 16
|
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||||
#define TEGRA_SE_AES_BLOCK_SIZE 16
|
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||||
#define TEGRA_SE_AES_MIN_KEY_SIZE 16
|
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
|
||||||
#define TEGRA_SE_AES_MAX_KEY_SIZE 32
|
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
|
||||||
#define TEGRA_SE_AES_IV_SIZE 16
|
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
|
||||||
#define TEGRA_SE_SHA_512_SIZE 64
|
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
|
||||||
#define TEGRA_SE_SHA_384_SIZE 48
|
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
|
||||||
#define TEGRA_SE_SHA_256_SIZE 32
|
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
|
||||||
#define TEGRA_SE_SHA_192_SIZE 24
|
|
||||||
#define TEGRA_SE_RNG_IV_SIZE 16
|
|
||||||
#define TEGRA_SE_RNG_DT_SIZE 16
|
|
||||||
#define TEGRA_SE_RNG_KEY_SIZE 16
|
|
||||||
#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \
|
|
||||||
TEGRA_SE_RNG_KEY_SIZE + \
|
|
||||||
TEGRA_SE_RNG_DT_SIZE)
|
|
||||||
|
|
||||||
#define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16
|
#define SE_CRYPTO_CONFIG_REG 0x304
|
||||||
#define TEGRA_SE_RSA512_DIGEST_SIZE 64
|
#define HASH_DISABLE 0
|
||||||
#define TEGRA_SE_RSA1024_DIGEST_SIZE 128
|
#define HASH_ENABLE 1
|
||||||
#define TEGRA_SE_RSA1536_DIGEST_SIZE 192
|
#define SE_CRYPTO_HASH(x) ((x) << 0)
|
||||||
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256
|
#define XOR_BYPASS 0
|
||||||
|
#define XOR_TOP 2
|
||||||
|
#define XOR_BOTTOM 3
|
||||||
|
#define SE_CRYPTO_XOR_POS(x) ((x) << 1)
|
||||||
|
#define INPUT_MEMORY 0
|
||||||
|
#define INPUT_RANDOM 1
|
||||||
|
#define INPUT_AESOUT 2
|
||||||
|
#define INPUT_LNR_CTR 3
|
||||||
|
#define SE_CRYPTO_INPUT_SEL(x) ((x) << 3)
|
||||||
|
#define VCTRAM_MEM 0
|
||||||
|
#define VCTRAM_AESOUT 2
|
||||||
|
#define VCTRAM_PREVMEM 3
|
||||||
|
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << 5)
|
||||||
|
#define IV_ORIGINAL 0
|
||||||
|
#define IV_UPDATED 1
|
||||||
|
#define SE_CRYPTO_IV_SEL(x) ((x) << 7)
|
||||||
|
#define CORE_DECRYPT 0
|
||||||
|
#define CORE_ENCRYPT 1
|
||||||
|
#define SE_CRYPTO_CORE_SEL(x) ((x) << 8)
|
||||||
|
#define SE_CRYPTO_KEYSCH_BYPASS BIT(10)
|
||||||
|
#define SE_CRYPTO_CTR_CNTN(x) ((x) << 11)
|
||||||
|
#define SE_CRYPTO_KEY_INDEX(x) ((x) << 24)
|
||||||
|
#define MEMIF_AHB 0
|
||||||
|
#define MEMIF_MCCIF 1
|
||||||
|
#define SE_CRYPTO_MEMIF(x) ((x) << 31)
|
||||||
|
|
||||||
#define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280
|
#define SE_CRYPTO_LINEAR_CTR_REG 0x308
|
||||||
#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
|
#define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4
|
||||||
|
|
||||||
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284
|
#define SE_CRYPTO_BLOCK_COUNT_REG 0x318
|
||||||
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
|
||||||
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
|
||||||
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
|
|
||||||
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
|
|
||||||
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
|
|
||||||
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
|
|
||||||
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
|
|
||||||
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
|
|
||||||
|
|
||||||
#define SE_KEY_READ_DISABLE_SHIFT 0
|
#define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C
|
||||||
#define SE_KEY_UPDATE_DISABLE_SHIFT 1
|
#define SE_KEYTABLE_PKT(x) ((x) << 0)
|
||||||
|
#define KEYS_0_3 0
|
||||||
|
#define KEYS_4_7 1
|
||||||
|
#define ORIGINAL_IV 2
|
||||||
|
#define UPDATED_IV 3
|
||||||
|
#define SE_KEYTABLE_QUAD(x) ((x) << 2)
|
||||||
|
#define SE_KEYTABLE_SLOT(x) ((x) << 4)
|
||||||
|
|
||||||
#define SE_CONTEXT_BUFER_SIZE 1072
|
#define SE_CRYPTO_KEYTABLE_DATA_REG 0x320
|
||||||
#define SE_CONTEXT_DRBG_BUFER_SIZE 2112
|
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0
|
#define SE_CRYPTO_KEYTABLE_DST_REG 0x330
|
||||||
#define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16
|
#define KEYS_0_3 0
|
||||||
#define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \
|
#define KEYS_4_7 1
|
||||||
(SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE)
|
#define ORIGINAL_IV 2
|
||||||
#define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16
|
#define UPDATED_IV 3
|
||||||
|
#define SE_KEYTABLE_DST_WORD_QUAD(x) ((x) << 0)
|
||||||
|
#define SE_KEYTABLE_DST_KEY_INDEX(x) ((x) << 8)
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \
|
#define SE_RNG_CONFIG_REG 0x340
|
||||||
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
|
#define MODE_NORMAL 0
|
||||||
#define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \
|
#define MODE_FORCE_INSTANTION 1
|
||||||
SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \
|
#define MODE_FORCE_RESEED 2
|
||||||
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
|
#define SE_RNG_CONFIG_MODE(x) ((x) << 0)
|
||||||
|
#define SRC_NONE 0
|
||||||
|
#define SRC_ENTROPY 1
|
||||||
|
#define SRC_LFSR 2
|
||||||
|
#define SE_RNG_CONFIG_SRC(x) ((x) << 2)
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_KEY_LENGTH 512
|
#define SE_RNG_SRC_CONFIG_REG 0x344
|
||||||
#define SE_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \
|
#define RO_ENTR_LOCK_DISABLE 0
|
||||||
SE_CONTEXT_SAVE_KEY_LENGTH)
|
#define RO_ENTR_LOCK_ENABLE 1
|
||||||
#define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \
|
#define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0)
|
||||||
SE_CONTEXT_SAVE_KEY_LENGTH)
|
#define RO_ENTR_DISABLE 0
|
||||||
|
#define RO_ENTR_ENABLE 1
|
||||||
|
#define SE_RNG_SRC_CONFIG_ENTR_SRC(x) ((x) << 1)
|
||||||
|
#define RO_HW_DIS_CYA_DISABLE 0
|
||||||
|
#define RO_HW_DIS_CYA_ENABLE 1
|
||||||
|
#define SE_RNG_SRC_CONFIG_HW_DIS_CYA(x) ((x) << 2)
|
||||||
|
#define SE_RNG_SRC_CONFIG_ENTR_SUBSMPL(x) ((x) << 4)
|
||||||
|
#define SE_RNG_SRC_CONFIG_ENTR_DATA_FLUSH BIT(8)
|
||||||
|
|
||||||
#define SE_CONTEXT_ORIGINAL_IV_LENGTH 256
|
#define SE_RNG_RESEED_INTERVAL_REG 0x348
|
||||||
|
|
||||||
#define SE_CONTEXT_UPDATED_IV_OFFSET (SE_CONTEXT_ORIGINAL_IV_OFFSET + \
|
#define SE_RSA_CONFIG 0x400
|
||||||
SE_CONTEXT_ORIGINAL_IV_LENGTH)
|
#define RSA_KEY_SLOT_ONE 0
|
||||||
#define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \
|
#define RSA_KEY_SLOT_TW0 1
|
||||||
SE_CONTEXT_ORIGINAL_IV_LENGTH)
|
#define RSA_KEY_SLOT(x) ((x) << 24)
|
||||||
|
|
||||||
#define SE_CONTEXT_UPDATED_IV_LENGTH 256
|
#define SE_RSA_KEY_SIZE_REG 0x404
|
||||||
|
#define RSA_KEY_WIDTH_512 0
|
||||||
|
#define RSA_KEY_WIDTH_1024 1
|
||||||
|
#define RSA_KEY_WIDTH_1536 2
|
||||||
|
#define RSA_KEY_WIDTH_2048 3
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET (SE_CONTEXT_UPDATED_IV_OFFSET + \
|
#define SE_RSA_EXP_SIZE_REG 0x408
|
||||||
SE_CONTEXT_UPDATED_IV_LENGTH)
|
|
||||||
#define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \
|
|
||||||
(SE11_CONTEXT_UPDATED_IV_OFFSET + \
|
|
||||||
SE_CONTEXT_UPDATED_IV_LENGTH)
|
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_RSA_KEYS_OFFSET SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET
|
#define SE_RSA_SECURITY_PERKEY_REG 0x40C
|
||||||
|
#define SE_RSA_KEY_LOCK_FLAG 0x80
|
||||||
|
#define SE_RSA_KEYTABLE_ACCESS_REG 0x410
|
||||||
|
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||||
|
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||||
|
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
|
||||||
|
#define SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
|
||||||
|
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
|
||||||
|
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG | SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG)
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_RSA_KEY_LENGTH 1024
|
#define SE_RSA_KEYTABLE_ADDR_REG 0x420
|
||||||
|
#define SE_RSA_KEYTABLE_PKT(x) ((x) << 0)
|
||||||
|
#define RSA_KEY_TYPE_EXP 0
|
||||||
|
#define RSA_KEY_TYPE_MOD 1
|
||||||
|
#define SE_RSA_KEYTABLE_TYPE(x) ((x) << 6)
|
||||||
|
#define RSA_KEY_NUM(x) ((x) << 7)
|
||||||
|
#define RSA_KEY_INPUT_MODE_REG 0
|
||||||
|
#define RSA_KEY_INPUT_MODE_DMA 1
|
||||||
|
#define SE_RSA_KEYTABLE_INPUT_MODE(x) ((x) << 8)
|
||||||
|
#define RSA_KEY_READ 0
|
||||||
|
#define RSA_KEY_WRITE 1
|
||||||
|
#define SE_RSA_KEY_OP(x) ((x) << 10)
|
||||||
|
|
||||||
#define SE_CONTEXT_SAVE_RSA_KNOWN_PATTERN_OFFSET \
|
#define SE_RSA_KEYTABLE_DATA_REG 0x424
|
||||||
(SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH)
|
|
||||||
|
|
||||||
#define SE_CONTEXT_KNOWN_PATTERN_SIZE 16
|
#define SE_RSA_OUTPUT_REG 0x428
|
||||||
|
#define SE_RSA_OUTPUT_REG_COUNT 64
|
||||||
|
|
||||||
#define TEGRA_SE_RSA_KEYSLOT_COUNT 2
|
#define SE_STATUS_REG 0x800
|
||||||
|
#define SE_STATUS_STATE_IDLE 0
|
||||||
|
#define SE_STATUS_STATE_BUSY 1
|
||||||
|
#define SE_STATUS_STATE_WAIT_OUT 2
|
||||||
|
#define SE_STATUS_STATE_WAIT_IN 3
|
||||||
|
#define SE_STATUS_STATE_MASK 3
|
||||||
|
|
||||||
#define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C
|
#define SE_ERR_STATUS_REG 0x804
|
||||||
#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
|
#define SE_ERR_STATUS_SE_NS_ACCESS BIT(0)
|
||||||
|
#define SE_ERR_STATUS_BUSY_REG_WR BIT(1)
|
||||||
|
#define SE_ERR_STATUS_DST BIT(2)
|
||||||
|
#define SE_ERR_STATUS_SRK_USAGE_LIMIT BIT(3)
|
||||||
|
#define SE_ERR_STATUS_TZRAM_NS_ACCESS BIT(24)
|
||||||
|
#define SE_ERR_STATUS_TZRAM_ADDRESS BIT(25)
|
||||||
|
|
||||||
#define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410
|
#define SE_MISC_REG 0x808
|
||||||
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
#define SE_ENTROPY_NEXT_192BIT BIT(0)
|
||||||
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
#define SE_ENTROPY_VN_BYPASS BIT(1)
|
||||||
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
|
#define SE_CLK_OVR_ON BIT(2)
|
||||||
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
|
|
||||||
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT BIT(2)
|
|
||||||
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7
|
|
||||||
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F
|
|
||||||
|
|
||||||
#define SE_RSA_KEYTABLE_ADDR 0x420
|
#define SE_SPARE_REG 0x80C
|
||||||
#define SE_RSA_KEYTABLE_DATA 0x424
|
#define SE_ERRATA_FIX_DISABLE 0
|
||||||
#define SE_RSA_OUTPUT 0x428
|
#define SE_ERRATA_FIX_ENABLE 1
|
||||||
|
#define SE_ECO(x) ((x) << 0)
|
||||||
|
|
||||||
#define RSA_KEY_READ 0
|
#endif
|
||||||
#define RSA_KEY_WRITE 1
|
|
||||||
#define SE_RSA_KEY_OP_SHIFT 10
|
|
||||||
#define SE_RSA_KEY_OP(x) ((x) << SE_RSA_KEY_OP_SHIFT)
|
|
||||||
|
|
||||||
#define RSA_KEY_INPUT_MODE_REG 0
|
|
||||||
#define RSA_KEY_INPUT_MODE_DMA 1
|
|
||||||
#define RSA_KEY_INPUT_MODE_SHIFT 8
|
|
||||||
#define RSA_KEY_INPUT_MODE(x) ((x) << RSA_KEY_INPUT_MODE_SHIFT)
|
|
||||||
|
|
||||||
#define RSA_KEY_SLOT_ONE 0
|
|
||||||
#define RSA_KEY_SLOT_TW0 1
|
|
||||||
#define RSA_KEY_NUM_SHIFT 7
|
|
||||||
#define RSA_KEY_NUM(x) ((x) << RSA_KEY_NUM_SHIFT)
|
|
||||||
|
|
||||||
#define RSA_KEY_TYPE_EXP 0
|
|
||||||
#define RSA_KEY_TYPE_MOD 1
|
|
||||||
#define RSA_KEY_TYPE_SHIFT 6
|
|
||||||
#define RSA_KEY_TYPE(x) ((x) << RSA_KEY_TYPE_SHIFT)
|
|
||||||
|
|
||||||
#define SE_RSA_KEY_SIZE_REG_OFFSET 0x404
|
|
||||||
#define SE_RSA_EXP_SIZE_REG_OFFSET 0x408
|
|
||||||
|
|
||||||
#define RSA_KEY_SLOT_SHIFT 24
|
|
||||||
#define RSA_KEY_SLOT(x) ((x) << RSA_KEY_SLOT_SHIFT)
|
|
||||||
#define SE_RSA_CONFIG 0x400
|
|
||||||
|
|
||||||
#define RSA_KEY_PKT_WORD_ADDR_SHIFT 0
|
|
||||||
#define RSA_KEY_PKT_WORD_ADDR(x) ((x) << RSA_KEY_PKT_WORD_ADDR_SHIFT)
|
|
||||||
|
|
||||||
#define RSA_KEY_WORD_ADDR_SHIFT 0
|
|
||||||
#define RSA_KEY_WORD_ADDR(x) ((x) << RSA_KEY_WORD_ADDR_SHIFT)
|
|
||||||
|
|
||||||
#define SE_RSA_KEYTABLE_PKT_SHIFT 0
|
|
||||||
#define SE_RSA_KEYTABLE_PKT(x) ((x) << SE_RSA_KEYTABLE_PKT_SHIFT)
|
|
||||||
|
|
||||||
#endif /* _CRYPTO_TEGRA_SE_H */
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2019 CTCaer
|
* Copyright (c) 2018-2021 CTCaer
|
||||||
* Copyright (c) 2018 balika011
|
* Copyright (c) 2018 balika011
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -70,7 +70,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
|||||||
u32 *pkg11_magic_off;
|
u32 *pkg11_magic_off;
|
||||||
|
|
||||||
bpmp_mmu_disable();
|
bpmp_mmu_disable();
|
||||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||||
|
|
||||||
// Enable clocks.
|
// Enable clocks.
|
||||||
clock_enable_host1x();
|
clock_enable_host1x();
|
||||||
@@ -190,7 +190,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
|||||||
if (kb == KB_TSEC_FW_EMU_COMPAT)
|
if (kb == KB_TSEC_FW_EMU_COMPAT)
|
||||||
{
|
{
|
||||||
u32 start = get_tmr_us();
|
u32 start = get_tmr_us();
|
||||||
u32 k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
|
u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
|
||||||
u32 key[16] = {0};
|
u32 key[16] = {0};
|
||||||
u32 kidx = 0;
|
u32 kidx = 0;
|
||||||
|
|
||||||
@@ -198,9 +198,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
|||||||
{
|
{
|
||||||
smmu_flush_all();
|
smmu_flush_all();
|
||||||
|
|
||||||
if (k != se[SE_KEYTABLE_DATA0_REG_OFFSET / 4])
|
if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
|
||||||
{
|
{
|
||||||
k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
|
k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
|
||||||
key[kidx++] = k;
|
key[kidx++] = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
|||||||
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
|
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
|
||||||
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
|
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
|
||||||
|
|
||||||
memcpy(tsec_keys, &buf, 0x10);
|
memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
out_free:;
|
out_free:;
|
||||||
@@ -284,7 +284,7 @@ out:;
|
|||||||
clock_disable_sor_safe();
|
clock_disable_sor_safe();
|
||||||
clock_disable_tsec();
|
clock_disable_tsec();
|
||||||
bpmp_mmu_enable();
|
bpmp_mmu_enable();
|
||||||
bpmp_clk_rate_set(BPMP_CLK_DEFAULT_BOOST);
|
bpmp_clk_rate_set(prev_fid);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2020 CTCaer
|
* Copyright (c) 2019-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -212,43 +212,45 @@ const u8 pll_divn[] = {
|
|||||||
//95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB.
|
//95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB.
|
||||||
};
|
};
|
||||||
|
|
||||||
bpmp_freq_t bpmp_clock_set = BPMP_CLK_NORMAL;
|
bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL;
|
||||||
|
|
||||||
void bpmp_clk_rate_get()
|
void bpmp_clk_rate_get()
|
||||||
{
|
{
|
||||||
bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3;
|
bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3;
|
||||||
|
|
||||||
if (clk_src_is_pllp)
|
if (clk_src_is_pllp)
|
||||||
bpmp_clock_set = BPMP_CLK_NORMAL;
|
bpmp_fid_current = BPMP_CLK_NORMAL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bpmp_clock_set = BPMP_CLK_HIGH_BOOST;
|
bpmp_fid_current = BPMP_CLK_HIGH_BOOST;
|
||||||
|
|
||||||
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
|
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
|
||||||
for (u32 i = 1; i < sizeof(pll_divn); i++)
|
for (u32 i = 1; i < sizeof(pll_divn); i++)
|
||||||
{
|
{
|
||||||
if (pll_divn[i] == pll_divn_curr)
|
if (pll_divn[i] == pll_divn_curr)
|
||||||
{
|
{
|
||||||
bpmp_clock_set = i;
|
bpmp_fid_current = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bpmp_clk_rate_set(bpmp_freq_t fid)
|
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid)
|
||||||
{
|
{
|
||||||
|
bpmp_freq_t prev_fid = bpmp_fid_current;
|
||||||
|
|
||||||
if (fid > (BPMP_CLK_MAX - 1))
|
if (fid > (BPMP_CLK_MAX - 1))
|
||||||
fid = BPMP_CLK_MAX - 1;
|
fid = BPMP_CLK_MAX - 1;
|
||||||
|
|
||||||
if (bpmp_clock_set == fid)
|
if (prev_fid == fid)
|
||||||
return;
|
return prev_fid;
|
||||||
|
|
||||||
if (fid)
|
if (fid)
|
||||||
{
|
{
|
||||||
if (bpmp_clock_set)
|
if (prev_fid)
|
||||||
{
|
{
|
||||||
// Restore to PLLP source during PLLC4 configuration.
|
// Restore to PLLP source during PLLC configuration.
|
||||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
|
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT.
|
||||||
msleep(1); // Wait a bit for clock source change.
|
msleep(1); // Wait a bit for clock source change.
|
||||||
}
|
}
|
||||||
@@ -269,7 +271,10 @@ void bpmp_clk_rate_set(bpmp_freq_t fid)
|
|||||||
// Disable PLLC to save power.
|
// Disable PLLC to save power.
|
||||||
clock_disable_pllc();
|
clock_disable_pllc();
|
||||||
}
|
}
|
||||||
bpmp_clock_set = fid;
|
bpmp_fid_current = fid;
|
||||||
|
|
||||||
|
// Return old fid in case of temporary swap.
|
||||||
|
return prev_fid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following functions halt BPMP to reduce power while sleeping.
|
// The following functions halt BPMP to reduce power while sleeping.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
* BPMP-Lite Cache/MMU and Frequency driver for Tegra X1
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2020 CTCaer
|
* Copyright (c) 2019-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -53,6 +53,7 @@ typedef enum
|
|||||||
BPMP_CLK_MAX
|
BPMP_CLK_MAX
|
||||||
} bpmp_freq_t;
|
} bpmp_freq_t;
|
||||||
|
|
||||||
|
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
|
||||||
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
|
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
|
||||||
|
|
||||||
void bpmp_mmu_maintenance(u32 op, bool force);
|
void bpmp_mmu_maintenance(u32 op, bool force);
|
||||||
@@ -60,7 +61,7 @@ void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply);
|
|||||||
void bpmp_mmu_enable();
|
void bpmp_mmu_enable();
|
||||||
void bpmp_mmu_disable();
|
void bpmp_mmu_disable();
|
||||||
void bpmp_clk_rate_get();
|
void bpmp_clk_rate_get();
|
||||||
void bpmp_clk_rate_set(bpmp_freq_t fid);
|
bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid);
|
||||||
void bpmp_usleep(u32 us);
|
void bpmp_usleep(u32 us);
|
||||||
void bpmp_msleep(u32 ms);
|
void bpmp_msleep(u32 ms);
|
||||||
void bpmp_halt();
|
void bpmp_halt();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2020 CTCaer
|
* Copyright (c) 2018-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
#include <storage/nx_sd.h>
|
#include <storage/nx_sd.h>
|
||||||
#include <storage/sdmmc.h>
|
#include <storage/sdmmc.h>
|
||||||
#include <thermal/fan.h>
|
#include <thermal/fan.h>
|
||||||
|
#include <thermal/tmp451.h>
|
||||||
#include <utils/util.h>
|
#include <utils/util.h>
|
||||||
|
|
||||||
extern boot_cfg_t b_cfg;
|
extern boot_cfg_t b_cfg;
|
||||||
@@ -87,6 +88,7 @@ static void _config_oscillators()
|
|||||||
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
|
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula.
|
||||||
static void _config_gpios(bool nx_hoag)
|
static void _config_gpios(bool nx_hoag)
|
||||||
{
|
{
|
||||||
// Clamp inputs when tristated.
|
// Clamp inputs when tristated.
|
||||||
@@ -263,7 +265,7 @@ static void _config_se_brom()
|
|||||||
FUSE(FUSE_PRIVATE_KEY3)
|
FUSE(FUSE_PRIVATE_KEY3)
|
||||||
};
|
};
|
||||||
// Set SBK to slot 14.
|
// Set SBK to slot 14.
|
||||||
se_aes_key_set(14, sbk, 0x10);
|
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
|
||||||
|
|
||||||
// Lock SBK from being read.
|
// Lock SBK from being read.
|
||||||
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
|
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
|
||||||
@@ -275,7 +277,7 @@ static void _config_se_brom()
|
|||||||
// This memset needs to happen here, else TZRAM will behave weirdly later on.
|
// This memset needs to happen here, else TZRAM will behave weirdly later on.
|
||||||
memset((void *)TZRAM_BASE, 0, 0x10000);
|
memset((void *)TZRAM_BASE, 0, 0x10000);
|
||||||
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
|
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
|
||||||
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F;
|
SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
|
||||||
|
|
||||||
// Clear the boot reason to avoid problems later
|
// Clear the boot reason to avoid problems later
|
||||||
PMC(APBDEV_PMC_SCRATCH200) = 0x0;
|
PMC(APBDEV_PMC_SCRATCH200) = 0x0;
|
||||||
@@ -419,19 +421,18 @@ void hw_init()
|
|||||||
bpmp_mmu_enable();
|
bpmp_mmu_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void hw_reinit_workaround(bool coreboot, u32 magic)
|
void hw_reinit_workaround(bool coreboot, u32 bl_magic)
|
||||||
{
|
{
|
||||||
// Disable BPMP max clock.
|
// Disable BPMP max clock.
|
||||||
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
|
||||||
|
|
||||||
#ifdef NYX
|
#ifdef NYX
|
||||||
// Deinit touchscreen, 5V regulators and Joy-Con.
|
// Disable temperature sensor, touchscreen, 5V regulators and Joy-Con.
|
||||||
touch_power_off();
|
tmp451_end();
|
||||||
set_fan_duty(0);
|
set_fan_duty(0);
|
||||||
|
touch_power_off();
|
||||||
jc_deinit();
|
jc_deinit();
|
||||||
regulator_5v_disable(REGULATOR_5V_ALL);
|
regulator_5v_disable(REGULATOR_5V_ALL);
|
||||||
clock_disable_uart(UART_B);
|
|
||||||
clock_disable_uart(UART_C);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Flush/disable MMU cache and set DRAM clock to 204MHz.
|
// Flush/disable MMU cache and set DRAM clock to 204MHz.
|
||||||
@@ -460,11 +461,22 @@ void hw_reinit_workaround(bool coreboot, u32 magic)
|
|||||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
|
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Power off display.
|
// Seamless display or display power off.
|
||||||
display_end();
|
switch (bl_magic)
|
||||||
|
{
|
||||||
|
case BL_MAGIC_CRBOOT_SLD:;
|
||||||
|
// Set pwm to 0%, switch to gpio mode and restore pwm duty.
|
||||||
|
u32 brightness = display_get_backlight_brightness();
|
||||||
|
display_backlight_brightness(0, 1000);
|
||||||
|
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO);
|
||||||
|
display_backlight_brightness(brightness, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
display_end();
|
||||||
|
}
|
||||||
|
|
||||||
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
|
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
|
||||||
if (magic == 0xBAADF00D)
|
if (bl_magic == BL_MAGIC_BROKEN_HWI)
|
||||||
{
|
{
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
|
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
|
||||||
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
|
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
|
||||||
|
|||||||
@@ -20,6 +20,9 @@
|
|||||||
|
|
||||||
#include <utils/types.h>
|
#include <utils/types.h>
|
||||||
|
|
||||||
|
#define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0.
|
||||||
|
#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit.
|
||||||
|
|
||||||
void hw_init();
|
void hw_init();
|
||||||
void hw_reinit_workaround(bool coreboot, u32 magic);
|
void hw_reinit_workaround(bool coreboot, u32 magic);
|
||||||
u32 hw_get_chip_id();
|
u32 hw_get_chip_id();
|
||||||
|
|||||||
@@ -122,7 +122,12 @@ u32 uart_get_IIR(u32 idx)
|
|||||||
{
|
{
|
||||||
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
|
uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]);
|
||||||
|
|
||||||
return uart->UART_IIR_FCR;
|
u32 iir = uart->UART_IIR_FCR & UART_IIR_INT_MASK;
|
||||||
|
|
||||||
|
if (iir & UART_IIR_NO_INT)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return ((iir >> 1) + 1); // Return encoded interrupt.
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_set_IIR(u32 idx)
|
void uart_set_IIR(u32 idx)
|
||||||
|
|||||||
@@ -54,6 +54,17 @@
|
|||||||
#define UART_IIR_FCR_RX_CLR 0x2
|
#define UART_IIR_FCR_RX_CLR 0x2
|
||||||
#define UART_IIR_FCR_EN_FIFO 0x1
|
#define UART_IIR_FCR_EN_FIFO 0x1
|
||||||
|
|
||||||
|
#define UART_IIR_NO_INT BIT(0)
|
||||||
|
#define UART_IIR_INT_MASK 0xF
|
||||||
|
/* Custom returned interrupt results. Actual interrupts are -1 */
|
||||||
|
#define UART_IIR_NOI 0 // No interrupt.
|
||||||
|
#define UART_IIR_MSI 1 // Modem status interrupt.
|
||||||
|
#define UART_IIR_THRI 2 // Transmitter holding register empty.
|
||||||
|
#define UART_IIR_RDI 3 // Receiver data interrupt.
|
||||||
|
#define UART_IIR_ERROR 4 // Overrun Error, Parity Error, Framing Error, Break.
|
||||||
|
#define UART_IIR_REDI 5 // Receiver end of data interrupt.
|
||||||
|
#define UART_IIR_RDTI 7 // Receiver data timeout interrupt.
|
||||||
|
|
||||||
#define UART_MCR_RTS 0x2
|
#define UART_MCR_RTS 0x2
|
||||||
#define UART_MCR_DTR 0x1
|
#define UART_MCR_DTR 0x1
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,11 @@
|
|||||||
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
|
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
|
||||||
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
|
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
|
||||||
|
|
||||||
|
#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */
|
||||||
|
#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */
|
||||||
|
#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */
|
||||||
|
#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */
|
||||||
|
|
||||||
/* class 11 */
|
/* class 11 */
|
||||||
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
|
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
|
||||||
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
|
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
|
||||||
@@ -182,7 +187,10 @@ c : clear by read
|
|||||||
/*
|
/*
|
||||||
* OCR bits are mostly in host.h
|
* OCR bits are mostly in host.h
|
||||||
*/
|
*/
|
||||||
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
|
#define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */
|
||||||
|
#define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */
|
||||||
|
#define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */
|
||||||
|
#define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Card Command Classes (CCC)
|
* Card Command Classes (CCC)
|
||||||
@@ -244,6 +252,7 @@ c : clear by read
|
|||||||
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
|
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
|
||||||
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
|
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
|
||||||
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
|
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
|
||||||
|
#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */
|
||||||
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
|
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
|
||||||
#define EXT_CSD_HPI_MGMT 161 /* R/W */
|
#define EXT_CSD_HPI_MGMT 161 /* R/W */
|
||||||
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
|
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2019 CTCaer
|
* Copyright (c) 2018-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -45,12 +45,15 @@ extern FATFS sd_fs;
|
|||||||
void sd_error_count_increment(u8 type);
|
void sd_error_count_increment(u8 type);
|
||||||
u16 *sd_get_error_count();
|
u16 *sd_get_error_count();
|
||||||
bool sd_get_card_removed();
|
bool sd_get_card_removed();
|
||||||
|
bool sd_get_card_initialized();
|
||||||
|
bool sd_get_card_mounted();
|
||||||
u32 sd_get_mode();
|
u32 sd_get_mode();
|
||||||
int sd_init_retry(bool power_cycle);
|
int sd_init_retry(bool power_cycle);
|
||||||
bool sd_initialize(bool power_cycle);
|
bool sd_initialize(bool power_cycle);
|
||||||
bool sd_mount();
|
bool sd_mount();
|
||||||
void sd_unmount();
|
void sd_unmount();
|
||||||
void sd_end();
|
void sd_end();
|
||||||
|
bool sd_is_gpt();
|
||||||
void *sd_file_read(const char *path, u32 *fsize);
|
void *sd_file_read(const char *path, u32 *fsize);
|
||||||
int sd_save_to_file(void *buf, u32 size, const char *filename);
|
int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Ramdisk driver for Tegra X1
|
* Ramdisk driver for Tegra X1
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 CTCaer
|
* Copyright (c) 2019-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -19,23 +19,40 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "ramdisk.h"
|
#include "ramdisk.h"
|
||||||
|
#include <libs/fatfs/diskio.h>
|
||||||
#include <mem/heap.h>
|
#include <mem/heap.h>
|
||||||
#include <utils/types.h>
|
#include <utils/types.h>
|
||||||
|
|
||||||
#include <memory_map.h>
|
#include <memory_map.h>
|
||||||
|
|
||||||
int ram_disk_init(FATFS *ram_fs)
|
static u32 disk_size = 0;
|
||||||
|
|
||||||
|
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size)
|
||||||
{
|
{
|
||||||
int res;
|
int res = 0;
|
||||||
u8 *buf = malloc(0x400000);
|
disk_size = ramdisk_size;
|
||||||
|
|
||||||
f_mount(NULL, "ram:", 1); // Unmount ramdisk.
|
// If ramdisk is not raw, format it.
|
||||||
|
if (ram_fs)
|
||||||
|
{
|
||||||
|
u8 *buf = malloc(0x400000);
|
||||||
|
|
||||||
res = f_mkfs("ram:", FM_EXFAT, RAMDISK_CLUSTER_SZ, buf, 0x400000); // Format as exFAT w/ 32KB cluster.
|
// Set ramdisk size.
|
||||||
if (!res)
|
ramdisk_size >>= 9;
|
||||||
res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk.
|
disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
|
||||||
|
|
||||||
free(buf);
|
// Unmount ramdisk.
|
||||||
|
f_mount(NULL, "ram:", 1);
|
||||||
|
|
||||||
|
// Format as exFAT w/ 32KB cluster with no MBR.
|
||||||
|
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);
|
||||||
|
|
||||||
|
// Mount ramdisk.
|
||||||
|
if (!res)
|
||||||
|
res = f_mount(ram_fs, "ram:", 1);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -45,7 +62,7 @@ int ram_disk_read(u32 sector, u32 sector_count, void *buf)
|
|||||||
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
|
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
|
||||||
u32 bytes_count = sector_count << 9;
|
u32 bytes_count = sector_count << 9;
|
||||||
|
|
||||||
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
|
if ((sector_off - RAM_DISK_ADDR) > disk_size)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
memcpy(buf, (void *)sector_off, bytes_count);
|
memcpy(buf, (void *)sector_off, bytes_count);
|
||||||
@@ -58,7 +75,7 @@ int ram_disk_write(u32 sector, u32 sector_count, const void *buf)
|
|||||||
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
|
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
|
||||||
u32 bytes_count = sector_count << 9;
|
u32 bytes_count = sector_count << 9;
|
||||||
|
|
||||||
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
|
if ((sector_off - RAM_DISK_ADDR) > disk_size)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
memcpy((void *)sector_off, buf, bytes_count);
|
memcpy((void *)sector_off, buf, bytes_count);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Ramdisk driver for Tegra X1
|
* Ramdisk driver for Tegra X1
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 CTCaer
|
* Copyright (c) 2019-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#define RAMDISK_CLUSTER_SZ 32768
|
#define RAMDISK_CLUSTER_SZ 32768
|
||||||
|
|
||||||
int ram_disk_init(FATFS *ram_fs);
|
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size);
|
||||||
int ram_disk_read(u32 sector, u32 sector_count, void *buf);
|
int ram_disk_read(u32 sector, u32 sector_count, void *buf);
|
||||||
int ram_disk_write(u32 sector, u32 sector_count, const void *buf);
|
int ram_disk_write(u32 sector, u32 sector_count, const void *buf);
|
||||||
|
|
||||||
|
|||||||
121
bdk/storage/sd.h
121
bdk/storage/sd.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
|
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
|
||||||
* Copyright (c) 2018 CTCaer
|
* Copyright (c) 2018-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -14,60 +14,79 @@
|
|||||||
/* SD commands type argument response */
|
/* SD commands type argument response */
|
||||||
/* class 0 */
|
/* class 0 */
|
||||||
/* This is basically the same command as for MMC with some quirks. */
|
/* This is basically the same command as for MMC with some quirks. */
|
||||||
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
||||||
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
||||||
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
||||||
|
|
||||||
/* class 10 */
|
/* class 10 */
|
||||||
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
||||||
|
|
||||||
/* class 5 */
|
/* class 5 */
|
||||||
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
||||||
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
||||||
|
|
||||||
/* Application commands */
|
/* Application commands */
|
||||||
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||||
#define SD_APP_SD_STATUS 13 /* adtc R1 */
|
#define SD_APP_SD_STATUS 13 /* adtc R1 */
|
||||||
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
|
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
|
||||||
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||||
#define SD_APP_SET_CLR_CARD_DETECT 42
|
#define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */
|
||||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||||
|
|
||||||
|
/* Application secure commands */
|
||||||
|
#define SD_APP_SECURE_READ_MULTI_BLOCK 18 /* adtc R1 */
|
||||||
|
#define SD_APP_SECURE_WRITE_MULTI_BLOCK 25 /* adtc R1 */
|
||||||
|
#define SD_APP_SECURE_WRITE_MKB 26 /* adtc R1 */
|
||||||
|
#define SD_APP_SECURE_ERASE 38 /* adtc R1b */
|
||||||
|
#define SD_APP_GET_MKB 43 /* adtc [31:0] See below R1 */
|
||||||
|
#define SD_APP_GET_MID 44 /* adtc R1 */
|
||||||
|
#define SD_APP_SET_CER_RN1 45 /* adtc R1 */
|
||||||
|
#define SD_APP_GET_CER_RN2 46 /* adtc R1 */
|
||||||
|
#define SD_APP_SET_CER_RES2 47 /* adtc R1 */
|
||||||
|
#define SD_APP_GET_CER_RES1 48 /* adtc R1 */
|
||||||
|
#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */
|
||||||
|
|
||||||
/* OCR bit definitions */
|
/* OCR bit definitions */
|
||||||
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
|
||||||
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||||
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
|
||||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
|
||||||
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
|
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
|
||||||
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
|
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
|
||||||
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
|
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
||||||
|
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||||
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
|
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||||
|
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||||
|
#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SD_SWITCH argument format:
|
* SD_SWITCH argument format:
|
||||||
*
|
*
|
||||||
* [31] Check (0) or switch (1)
|
* [31] Check (0) or switch (1)
|
||||||
* [30:24] Reserved (0)
|
* [30:24] Reserved (0)
|
||||||
* [23:20] Function group 6
|
* [23:20] Function group 6
|
||||||
* [19:16] Function group 5
|
* [19:16] Function group 5
|
||||||
* [15:12] Function group 4
|
* [15:12] Function group 4
|
||||||
* [11:8] Function group 3
|
* [11:8] Function group 3
|
||||||
* [7:4] Function group 2
|
* [7:4] Function group 2
|
||||||
* [3:0] Function group 1
|
* [3:0] Function group 1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SD_SEND_IF_COND argument format:
|
* SD_SEND_IF_COND argument format:
|
||||||
*
|
*
|
||||||
* [31:12] Reserved (0)
|
* [31:12] Reserved (0)
|
||||||
* [11:8] Host Voltage Supply Flags
|
* [11:8] Host Voltage Supply Flags
|
||||||
* [7:0] Check Pattern (0xAA)
|
* [7:0] Check Pattern (0xAA)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SCR field definitions
|
* SD_APP_GET_MKB argument format:
|
||||||
*/
|
*
|
||||||
|
* [31:24] Number of blocks to read (512 block size)
|
||||||
|
* [23:16] MKB ID
|
||||||
|
* [15:0] Block offset
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SCR field definitions
|
||||||
|
*/
|
||||||
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
|
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
|
||||||
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
|
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
|
||||||
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
|
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
|
||||||
@@ -75,14 +94,14 @@
|
|||||||
#define SD_SCR_BUS_WIDTH_4 (1<<2)
|
#define SD_SCR_BUS_WIDTH_4 (1<<2)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SD bus widths
|
* SD bus widths
|
||||||
*/
|
*/
|
||||||
#define SD_BUS_WIDTH_1 0
|
#define SD_BUS_WIDTH_1 0
|
||||||
#define SD_BUS_WIDTH_4 2
|
#define SD_BUS_WIDTH_4 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SD bus speeds
|
* SD bus speeds
|
||||||
*/
|
*/
|
||||||
#define UHS_SDR12_BUS_SPEED 0
|
#define UHS_SDR12_BUS_SPEED 0
|
||||||
#define HIGH_SPEED_BUS_SPEED 1
|
#define HIGH_SPEED_BUS_SPEED 1
|
||||||
#define UHS_SDR25_BUS_SPEED 1
|
#define UHS_SDR25_BUS_SPEED 1
|
||||||
@@ -112,19 +131,19 @@
|
|||||||
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
|
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SD_SWITCH mode
|
* SD_SWITCH mode
|
||||||
*/
|
*/
|
||||||
#define SD_SWITCH_CHECK 0
|
#define SD_SWITCH_CHECK 0
|
||||||
#define SD_SWITCH_SET 1
|
#define SD_SWITCH_SET 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SD_SWITCH function groups
|
* SD_SWITCH function groups
|
||||||
*/
|
*/
|
||||||
#define SD_SWITCH_GRP_ACCESS 0
|
#define SD_SWITCH_GRP_ACCESS 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SD_SWITCH access modes
|
* SD_SWITCH access modes
|
||||||
*/
|
*/
|
||||||
#define SD_SWITCH_ACCESS_DEF 0
|
#define SD_SWITCH_ACCESS_DEF 0
|
||||||
#define SD_SWITCH_ACCESS_HS 1
|
#define SD_SWITCH_ACCESS_HS 1
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2020 CTCaer
|
* Copyright (c) 2018-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -42,8 +42,8 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common functions for SD and MMC.
|
* Common functions for SD and MMC.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int _sdmmc_storage_check_card_status(u32 res)
|
static int _sdmmc_storage_check_card_status(u32 res)
|
||||||
{
|
{
|
||||||
@@ -88,20 +88,20 @@ static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u
|
|||||||
|
|
||||||
static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
|
static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
|
||||||
{
|
{
|
||||||
sdmmc_cmd_t cmd;
|
sdmmc_cmd_t cmdbuf;
|
||||||
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
|
sdmmc_init_cmd(&cmdbuf, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
|
||||||
|
|
||||||
return sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL);
|
return sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
|
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
|
||||||
{
|
{
|
||||||
sdmmc_cmd_t cmd;
|
sdmmc_cmd_t cmdbuf;
|
||||||
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
|
sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
|
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -111,14 +111,14 @@ static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
|
|||||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
|
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
|
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
|
||||||
{
|
{
|
||||||
sdmmc_cmd_t cmdbuf;
|
sdmmc_cmd_t cmdbuf;
|
||||||
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
|
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
|
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -145,6 +145,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
|||||||
sdmmc_cmd_t cmdbuf;
|
sdmmc_cmd_t cmdbuf;
|
||||||
sdmmc_req_t reqbuf;
|
sdmmc_req_t reqbuf;
|
||||||
|
|
||||||
|
// If SDSC convert block address to byte address.
|
||||||
|
if (!storage->has_sector_access)
|
||||||
|
sector <<= 9;
|
||||||
|
|
||||||
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
|
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
|
||||||
|
|
||||||
reqbuf.buf = buf;
|
reqbuf.buf = buf;
|
||||||
@@ -152,7 +156,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
|||||||
reqbuf.blksize = 512;
|
reqbuf.blksize = 512;
|
||||||
reqbuf.is_write = is_write;
|
reqbuf.is_write = is_write;
|
||||||
reqbuf.is_multi_block = 1;
|
reqbuf.is_multi_block = 1;
|
||||||
reqbuf.is_auto_cmd12 = 1;
|
reqbuf.is_auto_stop_trn = 1;
|
||||||
|
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
|
||||||
{
|
{
|
||||||
@@ -288,25 +292,25 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
|
|||||||
|
|
||||||
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
|
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
|
||||||
{
|
{
|
||||||
sdmmc_cmd_t cmd;
|
sdmmc_cmd_t cmdbuf;
|
||||||
|
|
||||||
u32 arg = 0;
|
u32 arg = 0;
|
||||||
switch (power)
|
switch (power)
|
||||||
{
|
{
|
||||||
case SDMMC_POWER_1_8:
|
case SDMMC_POWER_1_8:
|
||||||
arg = SD_OCR_CCS | SD_OCR_VDD_18;
|
arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDMMC_POWER_3_3:
|
case SDMMC_POWER_3_3:
|
||||||
arg = SD_OCR_CCS | SD_OCR_VDD_27_34;
|
arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
|
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
|
||||||
@@ -316,15 +320,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
|
|||||||
{
|
{
|
||||||
u32 timeout = get_tmr_ms() + 1500;
|
u32 timeout = get_tmr_ms() + 1500;
|
||||||
|
|
||||||
while (1)
|
while (true)
|
||||||
{
|
{
|
||||||
u32 cond = 0;
|
u32 cond = 0;
|
||||||
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
|
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Check if power up is done.
|
||||||
if (cond & MMC_CARD_BUSY)
|
if (cond & MMC_CARD_BUSY)
|
||||||
{
|
{
|
||||||
if (cond & SD_OCR_CCS)
|
// Check if card is high capacity.
|
||||||
|
if (cond & MMC_CARD_CCS)
|
||||||
storage->has_sector_access = 1;
|
storage->has_sector_access = 1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -362,7 +368,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
|
|||||||
case 3: /* MMC v3.1 - v3.3 */
|
case 3: /* MMC v3.1 - v3.3 */
|
||||||
case 4: /* MMC v4 */
|
case 4: /* MMC v4 */
|
||||||
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
||||||
storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2);
|
|
||||||
storage->cid.oemid = unstuff_bits(raw_cid, 104, 8);
|
storage->cid.oemid = unstuff_bits(raw_cid, 104, 8);
|
||||||
storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
|
storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
|
||||||
storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
|
storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
|
||||||
@@ -390,13 +395,14 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
|
|||||||
|
|
||||||
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
|
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
|
||||||
{
|
{
|
||||||
u32 *raw_csd = (u32 *)&(storage->raw_csd);
|
u32 *raw_csd = (u32 *)storage->raw_csd;
|
||||||
|
|
||||||
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
|
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
|
||||||
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
|
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
|
||||||
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
|
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
|
||||||
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
|
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
|
||||||
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
||||||
|
storage->sec_cnt = storage->csd.capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
||||||
@@ -407,16 +413,26 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
|||||||
storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
|
storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
|
||||||
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
|
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
|
||||||
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT];
|
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT];
|
||||||
storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
//storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
|
||||||
storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
|
//storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
|
||||||
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
|
//storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
|
||||||
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
|
|
||||||
|
|
||||||
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
|
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
|
||||||
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
|
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
|
||||||
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
|
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
|
||||||
|
|
||||||
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
storage->ext_csd.cache_size =
|
||||||
|
buf[EXT_CSD_CACHE_SIZE] |
|
||||||
|
(buf[EXT_CSD_CACHE_SIZE + 1] << 8) |
|
||||||
|
(buf[EXT_CSD_CACHE_SIZE + 2] << 16) |
|
||||||
|
(buf[EXT_CSD_CACHE_SIZE + 3] << 24);
|
||||||
|
storage->ext_csd.max_enh_mult =
|
||||||
|
(buf[EXT_CSD_MAX_ENH_SIZE_MULT] |
|
||||||
|
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) |
|
||||||
|
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) *
|
||||||
|
buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE];
|
||||||
|
|
||||||
|
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
||||||
@@ -430,7 +446,7 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
|||||||
reqbuf.num_sectors = 1;
|
reqbuf.num_sectors = 1;
|
||||||
reqbuf.is_write = 0;
|
reqbuf.is_write = 0;
|
||||||
reqbuf.is_multi_block = 0;
|
reqbuf.is_multi_block = 0;
|
||||||
reqbuf.is_auto_cmd12 = 0;
|
reqbuf.is_auto_stop_trn = 0;
|
||||||
|
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -559,19 +575,21 @@ out:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
|
static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
|
||||||
{
|
{
|
||||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2)))
|
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return _sdmmc_storage_check_status(storage);
|
return _sdmmc_storage_check_status(storage);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
||||||
{
|
{
|
||||||
memset(storage, 0, sizeof(sdmmc_storage_t));
|
memset(storage, 0, sizeof(sdmmc_storage_t));
|
||||||
storage->sdmmc = sdmmc;
|
storage->sdmmc = sdmmc;
|
||||||
storage->rca = 2; //TODO: this could be a config item.
|
storage->rca = 2; // Set default device address. This could be a config item.
|
||||||
|
|
||||||
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
|
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -587,7 +605,7 @@ DPRINTF("[MMC] went to idle state\n");
|
|||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[MMC] got op cond\n");
|
DPRINTF("[MMC] got op cond\n");
|
||||||
|
|
||||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
if (!_sdmmc_storage_get_cid(storage))
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[MMC] got cid\n");
|
DPRINTF("[MMC] got cid\n");
|
||||||
|
|
||||||
@@ -595,7 +613,7 @@ DPRINTF("[MMC] got cid\n");
|
|||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[MMC] set relative addr\n");
|
DPRINTF("[MMC] set relative addr\n");
|
||||||
|
|
||||||
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
|
if (!_sdmmc_storage_get_csd(storage))
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[MMC] got csd\n");
|
DPRINTF("[MMC] got csd\n");
|
||||||
_mmc_storage_parse_csd(storage);
|
_mmc_storage_parse_csd(storage);
|
||||||
@@ -612,13 +630,9 @@ DPRINTF("[MMC] card selected\n");
|
|||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[MMC] set blocklen to 512\n");
|
DPRINTF("[MMC] set blocklen to 512\n");
|
||||||
|
|
||||||
u32 *csd = (u32 *)storage->raw_csd;
|
// Check system specification version, only version 4.0 and later support below features.
|
||||||
//Check system specification version, only version 4.0 and later support below features.
|
if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
|
||||||
if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4)
|
|
||||||
{
|
|
||||||
storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
if (!_mmc_storage_switch_buswidth(storage, bus_width))
|
if (!_mmc_storage_switch_buswidth(storage, bus_width))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -628,21 +642,20 @@ DPRINTF("[MMC] switched buswidth\n");
|
|||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[MMC] got ext_csd\n");
|
DPRINTF("[MMC] got ext_csd\n");
|
||||||
|
|
||||||
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
|
_mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd.
|
||||||
//gfx_hexdump(0, ext_csd, 512);
|
//gfx_hexdump(0, ext_csd, 512);
|
||||||
|
|
||||||
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status.
|
/*
|
||||||
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end().
|
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
|
||||||
Additionally this works only when we put the device in idle mode which we don't after enabling it. */
|
|
||||||
if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2))
|
|
||||||
{
|
{
|
||||||
_mmc_storage_enable_bkops(storage);
|
_mmc_storage_enable_bkops(storage);
|
||||||
DPRINTF("[MMC] BKOPS enabled\n");
|
DPRINTF("[MMC] BKOPS enabled\n");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
|
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[MMC] succesfully switched to HS mode\n");
|
DPRINTF("[MMC] successfully switched to HS mode\n");
|
||||||
|
|
||||||
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
||||||
|
|
||||||
@@ -665,16 +678,16 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SD specific functions.
|
* SD specific functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out)
|
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmdbuf, sdmmc_req_t *req, u32 *blkcnt_out)
|
||||||
{
|
{
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
|
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out);
|
return sdmmc_execute_cmd(storage->sdmmc, cmdbuf, req, blkcnt_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state)
|
static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state)
|
||||||
@@ -685,67 +698,70 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
|
|||||||
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
|
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage)
|
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
|
||||||
{
|
{
|
||||||
sdmmc_cmd_t cmdbuf;
|
sdmmc_cmd_t cmdbuf;
|
||||||
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
|
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
|
||||||
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
|
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
return 1; // The SD Card is version 1.X
|
{
|
||||||
|
*is_sdsc = 1; // The SD Card is version 1.X
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Card version is >= 2.0, parse results.
|
// For Card version >= 2.0, parse results.
|
||||||
u32 resp = 0;
|
u32 resp = 0;
|
||||||
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5))
|
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
|
||||||
return 2; // Failed.
|
|
||||||
|
|
||||||
// Check if VHD was accepted and pattern was properly returned.
|
// Check if VHD was accepted and pattern was properly returned.
|
||||||
if ((resp & 0xFFF) == vhd_pattern)
|
if ((resp & 0xFFF) == vhd_pattern)
|
||||||
return 0;
|
return 1;
|
||||||
|
|
||||||
// Failed.
|
return 0;
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_uhs_support)
|
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support)
|
||||||
{
|
{
|
||||||
sdmmc_cmd_t cmdbuf;
|
sdmmc_cmd_t cmdbuf;
|
||||||
// Support for Current > 150mA
|
// Support for Current > 150mA
|
||||||
u32 arg = !is_version_1 ? SD_OCR_XPC : 0;
|
u32 arg = !is_sdsc ? SD_OCR_XPC : 0;
|
||||||
// Support for handling block-addressed SDHC cards
|
// Support for handling block-addressed SDHC cards
|
||||||
arg |= !is_version_1 ? SD_OCR_CCS : 0;
|
arg |= !is_sdsc ? SD_OCR_CCS : 0;
|
||||||
// Support for 1.8V
|
// Support for 1.8V
|
||||||
arg |= (bus_uhs_support && !is_version_1) ? SD_OCR_S18R : 0;
|
arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0;
|
||||||
// This is needed for most cards. Do not set bit7 even if 1.8V is supported.
|
// This is needed for most cards. Do not set bit7 even if 1.8V is supported.
|
||||||
arg |= SD_OCR_VDD_32_33;
|
arg |= SD_OCR_VDD_32_33;
|
||||||
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||||
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_version_1 ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
|
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
|
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_uhs_support)
|
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
|
||||||
{
|
{
|
||||||
u32 timeout = get_tmr_ms() + 1500;
|
u32 timeout = get_tmr_ms() + 1500;
|
||||||
|
|
||||||
while (1)
|
while (true)
|
||||||
{
|
{
|
||||||
u32 cond = 0;
|
u32 cond = 0;
|
||||||
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_uhs_support))
|
if (!_sd_storage_get_op_cond_once(storage, &cond, is_sdsc, bus_uhs_support))
|
||||||
break;
|
break;
|
||||||
if (cond & MMC_CARD_BUSY)
|
|
||||||
|
// Check if power up is done.
|
||||||
|
if (cond & SD_OCR_BUSY)
|
||||||
{
|
{
|
||||||
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
|
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
|
||||||
|
|
||||||
|
// Check if card is high capacity.
|
||||||
if (cond & SD_OCR_CCS)
|
if (cond & SD_OCR_CCS)
|
||||||
storage->has_sector_access = 1;
|
storage->has_sector_access = 1;
|
||||||
|
|
||||||
// Check if card supports 1.8V signaling.
|
// Check if card supports 1.8V signaling.
|
||||||
if (cond & SD_ROCR_S18A && bus_uhs_support)
|
if (cond & SD_ROCR_S18A && bus_uhs_support)
|
||||||
{
|
{
|
||||||
//The low voltage regulator configuration is valid for SDMMC1 only.
|
// Switch to 1.8V signaling.
|
||||||
if (storage->sdmmc->id == SDMMC_1 &&
|
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
|
||||||
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
|
|
||||||
{
|
{
|
||||||
if (!sdmmc_enable_low_voltage(storage->sdmmc))
|
if (!sdmmc_enable_low_voltage(storage->sdmmc))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -776,7 +792,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
|
|||||||
|
|
||||||
u32 timeout = get_tmr_ms() + 1500;
|
u32 timeout = get_tmr_ms() + 1500;
|
||||||
|
|
||||||
while (1)
|
while (true)
|
||||||
{
|
{
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
break;
|
break;
|
||||||
@@ -809,8 +825,9 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
|
|||||||
|
|
||||||
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
|
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
|
||||||
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
|
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
|
||||||
|
|
||||||
|
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
|
||||||
if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
|
if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
|
||||||
/* Check if Physical Layer Spec v3.0 is supported */
|
|
||||||
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
|
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
|
||||||
if (storage->scr.sda_spec3)
|
if (storage->scr.sda_spec3)
|
||||||
storage->scr.cmds = unstuff_bits(resp, 32, 2);
|
storage->scr.cmds = unstuff_bits(resp, 32, 2);
|
||||||
@@ -827,7 +844,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
|||||||
reqbuf.num_sectors = 1;
|
reqbuf.num_sectors = 1;
|
||||||
reqbuf.is_write = 0;
|
reqbuf.is_write = 0;
|
||||||
reqbuf.is_multi_block = 0;
|
reqbuf.is_multi_block = 0;
|
||||||
reqbuf.is_auto_cmd12 = 0;
|
reqbuf.is_auto_stop_trn = 0;
|
||||||
|
|
||||||
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
|
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -859,7 +876,7 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
|
|||||||
reqbuf.num_sectors = 1;
|
reqbuf.num_sectors = 1;
|
||||||
reqbuf.is_write = 0;
|
reqbuf.is_write = 0;
|
||||||
reqbuf.is_multi_block = 0;
|
reqbuf.is_multi_block = 0;
|
||||||
reqbuf.is_auto_cmd12 = 0;
|
reqbuf.is_auto_stop_trn = 0;
|
||||||
|
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -883,7 +900,7 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
|
|||||||
reqbuf.num_sectors = 1;
|
reqbuf.num_sectors = 1;
|
||||||
reqbuf.is_write = 0;
|
reqbuf.is_write = 0;
|
||||||
reqbuf.is_multi_block = 0;
|
reqbuf.is_multi_block = 0;
|
||||||
reqbuf.is_auto_cmd12 = 0;
|
reqbuf.is_auto_stop_trn = 0;
|
||||||
|
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1064,7 +1081,7 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
|||||||
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
|
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
|
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
|
||||||
{
|
{
|
||||||
u32 au_size = storage->ssr.uhs_au_size;
|
u32 au_size = storage->ssr.uhs_au_size;
|
||||||
|
|
||||||
@@ -1104,39 +1121,24 @@ u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
|
|||||||
|
|
||||||
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||||
{
|
{
|
||||||
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups
|
// unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups.
|
||||||
u32 raw_ssr1[4];
|
u32 raw_ssr1[4];
|
||||||
u32 raw_ssr2[4];
|
u32 raw_ssr2[4];
|
||||||
|
|
||||||
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12];
|
memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
|
||||||
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8];
|
memcpy(raw_ssr2, &storage->raw_ssr[16], 16);
|
||||||
raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4];
|
|
||||||
raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0];
|
|
||||||
|
|
||||||
raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28];
|
|
||||||
raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24];
|
|
||||||
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
|
|
||||||
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
|
|
||||||
|
|
||||||
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
|
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
|
||||||
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
|
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
|
||||||
|
|
||||||
switch(unstuff_bits(raw_ssr1, 440 - 384, 8))
|
u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
|
||||||
|
switch(speed_class)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
storage->ssr.speed_class = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
storage->ssr.speed_class = 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
storage->ssr.speed_class = 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
storage->ssr.speed_class = 6;
|
storage->ssr.speed_class = speed_class << 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
@@ -1144,19 +1146,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
|
storage->ssr.speed_class = speed_class;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
|
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
|
||||||
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
|
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
|
||||||
|
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
|
||||||
|
|
||||||
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
|
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
|
||||||
|
|
||||||
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
|
|
||||||
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
|
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||||
{
|
{
|
||||||
sdmmc_cmd_t cmdbuf;
|
sdmmc_cmd_t cmdbuf;
|
||||||
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0);
|
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0);
|
||||||
@@ -1167,11 +1168,11 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
|||||||
reqbuf.num_sectors = 1;
|
reqbuf.num_sectors = 1;
|
||||||
reqbuf.is_write = 0;
|
reqbuf.is_write = 0;
|
||||||
reqbuf.is_multi_block = 0;
|
reqbuf.is_multi_block = 0;
|
||||||
reqbuf.is_auto_cmd12 = 0;
|
reqbuf.is_auto_stop_trn = 0;
|
||||||
|
|
||||||
if (!(storage->csd.cmdclass & CCC_APP_SPEC))
|
if (!(storage->csd.cmdclass & CCC_APP_SPEC))
|
||||||
{
|
{
|
||||||
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
DPRINTF("[SD] ssr: Not supported\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1180,14 +1181,16 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
|||||||
|
|
||||||
u32 tmp = 0;
|
u32 tmp = 0;
|
||||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
||||||
//Prepare buffer for unstuff_bits
|
|
||||||
for (int i = 0; i < 64; i+=4)
|
// Convert buffer to LE.
|
||||||
|
for (int i = 0; i < 64; i += 4)
|
||||||
{
|
{
|
||||||
storage->raw_ssr[i + 3] = buf[i];
|
storage->raw_ssr[i + 3] = buf[i];
|
||||||
storage->raw_ssr[i + 2] = buf[i + 1];
|
storage->raw_ssr[i + 2] = buf[i + 1];
|
||||||
storage->raw_ssr[i + 1] = buf[i + 2];
|
storage->raw_ssr[i + 1] = buf[i + 2];
|
||||||
storage->raw_ssr[i] = buf[i + 3];
|
storage->raw_ssr[i] = buf[i + 3];
|
||||||
}
|
}
|
||||||
|
|
||||||
_sd_storage_parse_ssr(storage);
|
_sd_storage_parse_ssr(storage);
|
||||||
//gfx_hexdump(0, storage->raw_ssr, 64);
|
//gfx_hexdump(0, storage->raw_ssr, 64);
|
||||||
|
|
||||||
@@ -1198,18 +1201,18 @@ static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
|
|||||||
{
|
{
|
||||||
u32 *raw_cid = (u32 *)&(storage->raw_cid);
|
u32 *raw_cid = (u32 *)&(storage->raw_cid);
|
||||||
|
|
||||||
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
||||||
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
|
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
|
||||||
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
|
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
|
||||||
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
|
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
|
||||||
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
|
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
|
||||||
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
|
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
|
||||||
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
|
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
|
||||||
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
|
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
|
||||||
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
|
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
|
||||||
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
|
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
|
||||||
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
|
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
|
||||||
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
|
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||||
@@ -1224,6 +1227,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
|||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
||||||
|
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
@@ -1231,7 +1235,13 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
|||||||
storage->csd.capacity = storage->csd.c_size << 10;
|
storage->csd.capacity = storage->csd.c_size << 10;
|
||||||
storage->csd.read_blkbits = 9;
|
storage->csd.read_blkbits = 9;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
storage->sec_cnt = storage->csd.capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
|
static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
|
||||||
@@ -1261,8 +1271,10 @@ void sdmmc_storage_init_wait_sd()
|
|||||||
|
|
||||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
||||||
{
|
{
|
||||||
int is_version_1 = 0;
|
u32 tmp = 0;
|
||||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
int is_sdsc = 0;
|
||||||
|
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||||
|
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
|
||||||
|
|
||||||
DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
|
DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
|
||||||
|
|
||||||
@@ -1282,18 +1294,15 @@ DPRINTF("[SD] after init\n");
|
|||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] went to idle state\n");
|
DPRINTF("[SD] went to idle state\n");
|
||||||
|
|
||||||
is_version_1 = _sd_storage_send_if_cond(storage);
|
if (!_sd_storage_send_if_cond(storage, &is_sdsc))
|
||||||
if (is_version_1 == 2) // Failed.
|
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] after send if cond\n");
|
DPRINTF("[SD] after send if cond\n");
|
||||||
|
|
||||||
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
|
if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support))
|
||||||
|
|
||||||
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support))
|
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] got op cond\n");
|
DPRINTF("[SD] got op cond\n");
|
||||||
|
|
||||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
if (!_sdmmc_storage_get_cid(storage))
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] got cid\n");
|
DPRINTF("[SD] got cid\n");
|
||||||
_sd_storage_parse_cid(storage);
|
_sd_storage_parse_cid(storage);
|
||||||
@@ -1302,30 +1311,16 @@ DPRINTF("[SD] got cid\n");
|
|||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
|
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
|
||||||
|
|
||||||
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
|
if (!_sdmmc_storage_get_csd(storage))
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] got csd\n");
|
DPRINTF("[SD] got csd\n");
|
||||||
|
|
||||||
//Parse CSD.
|
|
||||||
_sd_storage_parse_csd(storage);
|
_sd_storage_parse_csd(storage);
|
||||||
switch (storage->csd.structure)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
storage->sec_cnt = storage->csd.capacity;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
storage->sec_cnt = storage->csd.c_size << 10;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!storage->is_low_voltage)
|
if (!storage->is_low_voltage)
|
||||||
{
|
{
|
||||||
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
|
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] after setup clock\n");
|
DPRINTF("[SD] after setup default clock\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_sdmmc_storage_select_card(storage))
|
if (!_sdmmc_storage_select_card(storage))
|
||||||
@@ -1336,19 +1331,17 @@ DPRINTF("[SD] card selected\n");
|
|||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] set blocklen to 512\n");
|
DPRINTF("[SD] set blocklen to 512\n");
|
||||||
|
|
||||||
u32 tmp = 0;
|
// Disconnect Card Detect resistor from DAT3.
|
||||||
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
|
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] cleared card detect\n");
|
DPRINTF("[SD] cleared card detect\n");
|
||||||
|
|
||||||
if (!_sd_storage_get_scr(storage, buf))
|
if (!_sd_storage_get_scr(storage, buf))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
//gfx_hexdump(0, storage->raw_scr, 8);
|
|
||||||
DPRINTF("[SD] got scr\n");
|
DPRINTF("[SD] got scr\n");
|
||||||
|
|
||||||
// Check if card supports a wider bus and if it's not SD Version 1.X
|
// If card supports a wider bus and if it's not SD Version 1.0 switch bus width.
|
||||||
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF))
|
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn)
|
||||||
{
|
{
|
||||||
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
|
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1370,7 +1363,7 @@ DPRINTF("[SD] enabled UHS\n");
|
|||||||
|
|
||||||
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
||||||
}
|
}
|
||||||
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF)) // Not default speed and not SD Version 1.x
|
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
|
||||||
{
|
{
|
||||||
if (!_sd_storage_enable_hs_high_volt(storage, buf))
|
if (!_sd_storage_enable_hs_high_volt(storage, buf))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1389,7 +1382,7 @@ DPRINTF("[SD] enabled HS\n");
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse additional card info from sd status.
|
// Parse additional card info from sd status.
|
||||||
if (_sd_storage_get_ssr(storage, buf))
|
if (sd_storage_get_ssr(storage, buf))
|
||||||
{
|
{
|
||||||
DPRINTF("[SD] got sd status\n");
|
DPRINTF("[SD] got sd status\n");
|
||||||
}
|
}
|
||||||
@@ -1400,14 +1393,14 @@ DPRINTF("[SD] got sd status\n");
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gamecard specific functions.
|
* Gamecard specific functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
||||||
{
|
{
|
||||||
u32 resp;
|
u32 resp;
|
||||||
sdmmc_cmd_t cmdbuf;
|
sdmmc_cmd_t cmdbuf;
|
||||||
sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1);
|
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1);
|
||||||
|
|
||||||
sdmmc_req_t reqbuf;
|
sdmmc_req_t reqbuf;
|
||||||
reqbuf.buf = buf;
|
reqbuf.buf = buf;
|
||||||
@@ -1415,7 +1408,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
|||||||
reqbuf.num_sectors = 1;
|
reqbuf.num_sectors = 1;
|
||||||
reqbuf.is_write = 1;
|
reqbuf.is_write = 1;
|
||||||
reqbuf.is_multi_block = 0;
|
reqbuf.is_multi_block = 0;
|
||||||
reqbuf.is_auto_cmd12 = 0;
|
reqbuf.is_auto_stop_trn = 0;
|
||||||
|
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2020 CTCaer
|
* Copyright (c) 2018-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -30,18 +30,18 @@ typedef enum _sdmmc_type
|
|||||||
|
|
||||||
EMMC_GPP = 0,
|
EMMC_GPP = 0,
|
||||||
EMMC_BOOT0 = 1,
|
EMMC_BOOT0 = 1,
|
||||||
EMMC_BOOT1 = 2
|
EMMC_BOOT1 = 2,
|
||||||
|
EMMC_RPMB = 3
|
||||||
} sdmmc_type;
|
} sdmmc_type;
|
||||||
|
|
||||||
typedef struct _mmc_cid
|
typedef struct _mmc_cid
|
||||||
{
|
{
|
||||||
u32 manfid;
|
u32 manfid;
|
||||||
u8 prod_name[8];
|
u8 prod_name[8];
|
||||||
u8 card_bga;
|
|
||||||
u8 prv;
|
|
||||||
u32 serial;
|
u32 serial;
|
||||||
u16 oemid;
|
u16 oemid;
|
||||||
u16 year;
|
u16 year;
|
||||||
|
u8 prv;
|
||||||
u8 hwrev;
|
u8 hwrev;
|
||||||
u8 fwrev;
|
u8 fwrev;
|
||||||
u8 month;
|
u8 month;
|
||||||
@@ -65,19 +65,20 @@ typedef struct _mmc_csd
|
|||||||
|
|
||||||
typedef struct _mmc_ext_csd
|
typedef struct _mmc_ext_csd
|
||||||
{
|
{
|
||||||
u32 sectors;
|
//u8 bkops; /* background support bit */
|
||||||
int bkops; /* background support bit */
|
//u8 bkops_en; /* manual bkops enable bit */
|
||||||
int bkops_en; /* manual bkops enable bit */
|
//u8 bkops_status; /* 246 */
|
||||||
u8 rev;
|
u8 rev;
|
||||||
u8 ext_struct; /* 194 */
|
u8 ext_struct; /* 194 */
|
||||||
u8 card_type; /* 196 */
|
u8 card_type; /* 196 */
|
||||||
u8 bkops_status; /* 246 */
|
|
||||||
u8 pre_eol_info;
|
u8 pre_eol_info;
|
||||||
u8 dev_life_est_a;
|
u8 dev_life_est_a;
|
||||||
u8 dev_life_est_b;
|
u8 dev_life_est_b;
|
||||||
u8 boot_mult;
|
u8 boot_mult;
|
||||||
u8 rpmb_mult;
|
u8 rpmb_mult;
|
||||||
u16 dev_version;
|
u16 dev_version;
|
||||||
|
u32 cache_size;
|
||||||
|
u32 max_enh_mult;
|
||||||
} mmc_ext_csd_t;
|
} mmc_ext_csd_t;
|
||||||
|
|
||||||
typedef struct _sd_scr
|
typedef struct _sd_scr
|
||||||
@@ -90,13 +91,13 @@ typedef struct _sd_scr
|
|||||||
|
|
||||||
typedef struct _sd_ssr
|
typedef struct _sd_ssr
|
||||||
{
|
{
|
||||||
u8 bus_width;
|
u8 bus_width;
|
||||||
u8 speed_class;
|
u8 speed_class;
|
||||||
u8 uhs_grade;
|
u8 uhs_grade;
|
||||||
u8 video_class;
|
u8 video_class;
|
||||||
u8 app_class;
|
u8 app_class;
|
||||||
u8 au_size;
|
u8 au_size;
|
||||||
u8 uhs_au_size;
|
u8 uhs_au_size;
|
||||||
u32 protected_size;
|
u32 protected_size;
|
||||||
} sd_ssr_t;
|
} sd_ssr_t;
|
||||||
|
|
||||||
@@ -130,6 +131,7 @@ void sdmmc_storage_init_wait_sd();
|
|||||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
|
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
|
||||||
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
||||||
|
|
||||||
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage);
|
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
|
||||||
|
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2020 CTCaer
|
* Copyright (c) 2018-2021 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
|
|||||||
*blkcnt_out = blkcnt;
|
*blkcnt_out = blkcnt;
|
||||||
|
|
||||||
u32 trnmode = SDHCI_TRNS_DMA;
|
u32 trnmode = SDHCI_TRNS_DMA;
|
||||||
|
|
||||||
|
// Set mulitblock request.
|
||||||
if (req->is_multi_block)
|
if (req->is_multi_block)
|
||||||
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
|
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
|
||||||
|
|
||||||
|
// Set request direction.
|
||||||
if (!req->is_write)
|
if (!req->is_write)
|
||||||
trnmode |= SDHCI_TRNS_READ;
|
trnmode |= SDHCI_TRNS_READ;
|
||||||
if (req->is_auto_cmd12)
|
|
||||||
trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12;
|
// Automatic send of stop transmission or set block count cmd.
|
||||||
|
if (req->is_auto_stop_trn)
|
||||||
|
trnmode |= SDHCI_TRNS_AUTO_CMD12;
|
||||||
|
//else if (req->is_auto_set_blkcnt)
|
||||||
|
// trnmode |= SDHCI_TRNS_AUTO_CMD23;
|
||||||
|
|
||||||
sdmmc->regs->trnmod = trnmode;
|
sdmmc->regs->trnmod = trnmode;
|
||||||
|
|
||||||
@@ -1070,7 +1078,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
|||||||
if (blkcnt_out)
|
if (blkcnt_out)
|
||||||
*blkcnt_out = blkcnt;
|
*blkcnt_out = blkcnt;
|
||||||
|
|
||||||
if (req->is_auto_cmd12)
|
if (req->is_auto_stop_trn)
|
||||||
sdmmc->rsp3 = sdmmc->regs->rspreg3;
|
sdmmc->rsp3 = sdmmc->regs->rspreg3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1371,12 +1379,12 @@ void sdmmc_end(sdmmc_t *sdmmc)
|
|||||||
_sdmmc_sd_clock_disable(sdmmc);
|
_sdmmc_sd_clock_disable(sdmmc);
|
||||||
// Disable SDMMC power.
|
// Disable SDMMC power.
|
||||||
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
|
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
|
||||||
|
_sdmmc_commit_changes(sdmmc);
|
||||||
|
|
||||||
// Disable SD card power.
|
// Disable SD card power.
|
||||||
if (sdmmc->id == SDMMC_1)
|
if (sdmmc->id == SDMMC_1)
|
||||||
sdmmc1_disable_power();
|
sdmmc1_disable_power();
|
||||||
|
|
||||||
_sdmmc_commit_changes(sdmmc);
|
|
||||||
clock_sdmmc_disable(sdmmc->id);
|
clock_sdmmc_disable(sdmmc->id);
|
||||||
sdmmc->clock_stopped = 1;
|
sdmmc->clock_stopped = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ typedef struct _sdmmc_req_t
|
|||||||
u32 num_sectors;
|
u32 num_sectors;
|
||||||
int is_write;
|
int is_write;
|
||||||
int is_multi_block;
|
int is_multi_block;
|
||||||
int is_auto_cmd12;
|
int is_auto_stop_trn;
|
||||||
} sdmmc_req_t;
|
} sdmmc_req_t;
|
||||||
|
|
||||||
int sdmmc_get_io_power(sdmmc_t *sdmmc);
|
int sdmmc_get_io_power(sdmmc_t *sdmmc);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
void set_fan_duty(u32 duty)
|
void set_fan_duty(u32 duty)
|
||||||
{
|
{
|
||||||
static bool fan_init = false;
|
static bool fan_init = false;
|
||||||
static u16 curr_duty = -1;
|
static u16 curr_duty = -1;
|
||||||
|
|
||||||
if (curr_duty == duty)
|
if (curr_duty == duty)
|
||||||
return;
|
return;
|
||||||
@@ -79,15 +79,14 @@ void get_fan_speed(u32 *duty, u32 *rpm)
|
|||||||
{
|
{
|
||||||
if (rpm)
|
if (rpm)
|
||||||
{
|
{
|
||||||
u32 irq_count = 1;
|
u32 irq_count = 0;
|
||||||
bool should_read = true;
|
bool should_read = true;
|
||||||
bool irq_val = 0;
|
|
||||||
|
|
||||||
// Poll irqs for 2 seconds.
|
// Poll irqs for 2 seconds. (5 seconds for accurate count).
|
||||||
int timer = get_tmr_us() + 1000000;
|
int timer = get_tmr_us() + 2000000;
|
||||||
while (timer - get_tmr_us())
|
while ((timer - get_tmr_us()) > 0)
|
||||||
{
|
{
|
||||||
irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7);
|
bool irq_val = gpio_read(GPIO_PORT_S, GPIO_PIN_7);
|
||||||
if (irq_val && should_read)
|
if (irq_val && should_read)
|
||||||
{
|
{
|
||||||
irq_count++;
|
irq_count++;
|
||||||
@@ -97,8 +96,11 @@ void get_fan_speed(u32 *duty, u32 *rpm)
|
|||||||
should_read = true;
|
should_read = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Halve the irq count.
|
||||||
|
irq_count /= 2;
|
||||||
|
|
||||||
// Calculate rpm based on triggered interrupts.
|
// Calculate rpm based on triggered interrupts.
|
||||||
*rpm = 60000000 / ((1000000 * 2) / irq_count);
|
*rpm = irq_count * (60 / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (duty)
|
if (duty)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SOC/PCB Temperature driver for Nintendo Switch's TI TMP451
|
* SOC/PCB Temperature driver for Nintendo Switch's TI TMP451
|
||||||
*
|
*
|
||||||
* Copyright (c) 2018 CTCaer
|
* Copyright (c) 2018-2020 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -16,7 +16,9 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <soc/hw_init.h>
|
||||||
#include <soc/i2c.h>
|
#include <soc/i2c.h>
|
||||||
|
#include <soc/t210.h>
|
||||||
#include <thermal/tmp451.h>
|
#include <thermal/tmp451.h>
|
||||||
|
|
||||||
u16 tmp451_get_soc_temp(bool intenger)
|
u16 tmp451_get_soc_temp(bool intenger)
|
||||||
@@ -56,6 +58,20 @@ void tmp451_init()
|
|||||||
// Disable ALARM and Range to 0 - 127 oC.
|
// Disable ALARM and Range to 0 - 127 oC.
|
||||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80);
|
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80);
|
||||||
|
|
||||||
|
// Set remote sensor offsets based on SoC.
|
||||||
|
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
|
||||||
|
{
|
||||||
|
// Set offset to 0 oC for Erista.
|
||||||
|
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0);
|
||||||
|
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set offset to -12.5 oC for Mariko.
|
||||||
|
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0xF3); // - 13 oC.
|
||||||
|
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0x80); // + 0.5 oC.
|
||||||
|
}
|
||||||
|
|
||||||
// Set conversion rate to 32/s and make a read to update the reg.
|
// Set conversion rate to 32/s and make a read to update the reg.
|
||||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9);
|
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9);
|
||||||
tmp451_get_soc_temp(false);
|
tmp451_get_soc_temp(false);
|
||||||
@@ -63,3 +79,9 @@ void tmp451_init()
|
|||||||
// Set rate to every 4 seconds.
|
// Set rate to every 4 seconds.
|
||||||
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2);
|
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tmp451_end()
|
||||||
|
{
|
||||||
|
// Place into shutdown mode to conserve power.
|
||||||
|
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0xC0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,11 +32,15 @@
|
|||||||
#define TMP451_SOC_TMP_DEC_REG 0x10
|
#define TMP451_SOC_TMP_DEC_REG 0x10
|
||||||
#define TMP451_PCB_TMP_DEC_REG 0x15
|
#define TMP451_PCB_TMP_DEC_REG 0x15
|
||||||
|
|
||||||
|
#define TMP451_SOC_TMP_OFH_REG 0x11
|
||||||
|
#define TMP451_SOC_TMP_OFL_REG 0x12
|
||||||
|
|
||||||
// If input is false, the return value is packed. MSByte is the integer in oC
|
// If input is false, the return value is packed. MSByte is the integer in oC
|
||||||
// and the LSByte is the decimal point truncated to 2 decimal places.
|
// and the LSByte is the decimal point truncated to 2 decimal places.
|
||||||
// Otherwise it's an integer oC.
|
// Otherwise it's an integer oC.
|
||||||
u16 tmp451_get_soc_temp(bool integer);
|
u16 tmp451_get_soc_temp(bool integer);
|
||||||
u16 tmp451_get_pcb_temp(bool integer);
|
u16 tmp451_get_pcb_temp(bool integer);
|
||||||
void tmp451_init();
|
void tmp451_init();
|
||||||
|
void tmp451_end();
|
||||||
|
|
||||||
#endif /* __TMP451_H_ */
|
#endif /* __TMP451_H_ */
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ typedef struct _bulk_ctxt_t {
|
|||||||
typedef struct _usbd_gadget_ums_t {
|
typedef struct _usbd_gadget_ums_t {
|
||||||
bulk_ctxt_t bulk_ctxt;
|
bulk_ctxt_t bulk_ctxt;
|
||||||
|
|
||||||
int cmnd_size;
|
u32 cmnd_size;
|
||||||
u8 cmnd[SCSI_MAX_CMD_SZ];
|
u8 cmnd[SCSI_MAX_CMD_SZ];
|
||||||
|
|
||||||
u32 lun_idx; // lun index
|
u32 lun_idx; // lun index
|
||||||
@@ -583,22 +583,20 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
|||||||
|
|
||||||
while (amount_left_to_write > 0)
|
while (amount_left_to_write > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Queue a request for more data from the host */
|
/* Queue a request for more data from the host */
|
||||||
if (amount_left_to_req)
|
if (amount_left_to_req > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Limit write to max supported read from EP OUT.
|
// Limit write to max supported read from EP OUT.
|
||||||
amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER);
|
amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER);
|
||||||
|
|
||||||
if (usb_lba_offset >= ums->lun.num_sectors) //////////Check if it works with concurrency
|
if (usb_lba_offset >= ums->lun.num_sectors)
|
||||||
{
|
{
|
||||||
ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!");
|
ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!");
|
||||||
amount_left_to_req = 0;
|
|
||||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||||
ums->lun.sense_data_info = usb_lba_offset;
|
ums->lun.sense_data_info = usb_lba_offset;
|
||||||
ums->lun.info_valid = 1;
|
ums->lun.info_valid = 1;
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the next buffer.
|
// Get the next buffer.
|
||||||
@@ -1114,7 +1112,7 @@ static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bul
|
|||||||
|
|
||||||
// Check whether the command is properly formed and whether its data size
|
// Check whether the command is properly formed and whether its data size
|
||||||
// and direction agree with the values we already have.
|
// and direction agree with the values we already have.
|
||||||
static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, int cmnd_size,
|
static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, u32 cmnd_size,
|
||||||
enum data_direction data_dir, u32 mask, int needs_medium)
|
enum data_direction data_dir, u32 mask, int needs_medium)
|
||||||
{
|
{
|
||||||
//const char dirletter[4] = {'u', 'o', 'i', 'n'};
|
//const char dirletter[4] = {'u', 'o', 'i', 'n'};
|
||||||
@@ -1608,7 +1606,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
|||||||
|
|
||||||
/* Is the CBW meaningful? */
|
/* Is the CBW meaningful? */
|
||||||
if (cbw->Lun >= UMS_MAX_LUN || cbw->Flags & ~USB_BULK_IN_FLAG ||
|
if (cbw->Lun >= UMS_MAX_LUN || cbw->Flags & ~USB_BULK_IN_FLAG ||
|
||||||
cbw->Length <= 0 || cbw->Length > SCSI_MAX_CMD_SZ)
|
cbw->Length == 0 || cbw->Length > SCSI_MAX_CMD_SZ)
|
||||||
{
|
{
|
||||||
gfx_printf("USB: non-meaningful CBW: lun = %X, flags = 0x%X, cmdlen %X\n",
|
gfx_printf("USB: non-meaningful CBW: lun = %X, flags = 0x%X, cmdlen %X\n",
|
||||||
cbw->Lun, cbw->Flags, cbw->Length);
|
cbw->Lun, cbw->Flags, cbw->Length);
|
||||||
@@ -1837,6 +1835,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
|||||||
// Initialize sdmmc.
|
// Initialize sdmmc.
|
||||||
if (usbs->type == MMC_SD)
|
if (usbs->type == MMC_SD)
|
||||||
{
|
{
|
||||||
|
sd_end();
|
||||||
sd_mount();
|
sd_mount();
|
||||||
sd_unmount();
|
sd_unmount();
|
||||||
ums.lun.sdmmc = &sd_sdmmc;
|
ums.lun.sdmmc = &sd_sdmmc;
|
||||||
@@ -1907,7 +1906,10 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
|||||||
send_status(&ums, &ums.bulk_ctxt);
|
send_status(&ums, &ums.bulk_ctxt);
|
||||||
} while (ums.state != UMS_STATE_TERMINATED);
|
} while (ums.state != UMS_STATE_TERMINATED);
|
||||||
|
|
||||||
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected");
|
if (ums.lun.prevent_medium_removal)
|
||||||
|
ums.set_text(ums.label, "#FFDD00 Error:# Disk unsafely ejected");
|
||||||
|
else
|
||||||
|
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected");
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ u8 btn_read()
|
|||||||
res |= BTN_VOL_DOWN;
|
res |= BTN_VOL_DOWN;
|
||||||
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
|
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
|
||||||
res |= BTN_VOL_UP;
|
res |= BTN_VOL_UP;
|
||||||
if (i2c_recv_byte(4, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & 0x4)
|
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0)
|
||||||
res |= BTN_POWER;
|
res |= BTN_POWER;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,16 +21,16 @@
|
|||||||
#include <mem/heap.h>
|
#include <mem/heap.h>
|
||||||
#include <utils/types.h>
|
#include <utils/types.h>
|
||||||
|
|
||||||
|
#define MAX_ENTRIES 64
|
||||||
|
|
||||||
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
|
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
|
||||||
{
|
{
|
||||||
u8 max_entries = 61;
|
|
||||||
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
u32 i = 0, j = 0, k = 0;
|
u32 i = 0, j = 0, k = 0;
|
||||||
DIR dir;
|
DIR dir;
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
|
|
||||||
char *dir_entries = (char *)calloc(max_entries, 256);
|
char *dir_entries = (char *)calloc(MAX_ENTRIES, 256);
|
||||||
char *temp = (char *)calloc(1, 256);
|
char *temp = (char *)calloc(1, 256);
|
||||||
|
|
||||||
if (!pattern && !f_opendir(&dir, directory))
|
if (!pattern && !f_opendir(&dir, directory))
|
||||||
@@ -49,7 +49,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
|
|||||||
{
|
{
|
||||||
strcpy(dir_entries + (k * 256), fno.fname);
|
strcpy(dir_entries + (k * 256), fno.fname);
|
||||||
k++;
|
k++;
|
||||||
if (k > (max_entries - 1))
|
if (k > (MAX_ENTRIES - 1))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile
|
|||||||
{
|
{
|
||||||
strcpy(dir_entries + (k * 256), fno.fname);
|
strcpy(dir_entries + (k * 256), fno.fname);
|
||||||
k++;
|
k++;
|
||||||
if (k > (max_entries - 1))
|
if (k > (MAX_ENTRIES - 1))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
res = f_findnext(&dir, &fno);
|
res = f_findnext(&dir, &fno);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ static u32 _putn(char *buffer, u32 v, int base, char fill, int fcnt) {
|
|||||||
return _puts(buffer, p);
|
return _puts(buffer, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 sprintf(char *buffer, const char *fmt, ...) {
|
u32 s_printf(char *buffer, const char *fmt, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int fill, fcnt;
|
int fill, fcnt;
|
||||||
u32 count = 0;
|
u32 count = 0;
|
||||||
|
|||||||
@@ -19,6 +19,6 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
u32 sprintf(char *buffer, const char *fmt, ...);
|
u32 s_printf(char *buffer, const char *fmt, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#define ALWAYS_INLINE inline __attribute__((always_inline))
|
#define ALWAYS_INLINE inline __attribute__((always_inline))
|
||||||
|
|
||||||
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||||
#define ALIGN_DOWN(x, a) (((x) - ((a) - 1)) & ~((a) - 1))
|
#define ALIGN_DOWN(x, a) ((x) & ~((a) - 1))
|
||||||
#define BIT(n) (1U << (n))
|
#define BIT(n) (1U << (n))
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
|||||||
@@ -167,10 +167,10 @@ void power_set_state(power_state_t state)
|
|||||||
default:
|
default:
|
||||||
// Enable/Disable soft reset wake event.
|
// Enable/Disable soft reset wake event.
|
||||||
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
|
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
|
||||||
if (state == POWER_OFF_RESET)
|
if (state == POWER_OFF_RESET) // Do not wake up after power off.
|
||||||
reg &= ~MAX77620_ONOFFCNFG2_SFT_RST_WK; // Do not wake up after power off.
|
reg &= ~(MAX77620_ONOFFCNFG2_SFT_RST_WK | MAX77620_ONOFFCNFG2_WK_ALARM1 | MAX77620_ONOFFCNFG2_WK_ALARM2);
|
||||||
else // POWER_OFF_REBOOT.
|
else // POWER_OFF_REBOOT. Wake up after power off.
|
||||||
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; // Wake up after power off.
|
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
|
||||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
|
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
|
||||||
|
|
||||||
// Initiate power down sequence and generate a reset (regulators' state resets).
|
// Initiate power down sequence and generate a reset (regulators' state resets).
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2020 CTCaer
|
* Copyright (c) 2018 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -21,8 +21,6 @@
|
|||||||
#include <utils/types.h>
|
#include <utils/types.h>
|
||||||
#include <mem/minerva.h>
|
#include <mem/minerva.h>
|
||||||
|
|
||||||
#define NYX_NEW_INFO 0x3058594E
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
REBOOT_RCM, // PMC reset. Enter RCM mode.
|
REBOOT_RCM, // PMC reset. Enter RCM mode.
|
||||||
@@ -53,6 +51,8 @@ typedef enum
|
|||||||
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
|
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
|
||||||
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
|
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
|
||||||
|
|
||||||
|
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
|
||||||
|
|
||||||
typedef struct _cfg_op_t
|
typedef struct _cfg_op_t
|
||||||
{
|
{
|
||||||
u32 off;
|
u32 off;
|
||||||
@@ -84,9 +84,9 @@ typedef struct _nyx_storage_t
|
|||||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
||||||
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
|
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
|
||||||
|
|
||||||
u32 get_tmr_us();
|
u32 get_tmr_us();
|
||||||
u32 get_tmr_ms();
|
u32 get_tmr_ms();
|
||||||
u32 get_tmr_s();
|
u32 get_tmr_s();
|
||||||
void usleep(u32 us);
|
void usleep(u32 us);
|
||||||
void msleep(u32 ms);
|
void msleep(u32 ms);
|
||||||
|
|
||||||
|
|||||||
63
loader/Makefile
Normal file
63
loader/Makefile
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITARM)/base_rules
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
LDR_LOAD_ADDR := 0x40007000
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
TARGET := loader
|
||||||
|
BUILDDIR := ../build
|
||||||
|
OUTPUTDIR := ../output
|
||||||
|
BDKDIR := bdk
|
||||||
|
BDKINC := -I../$(BDKDIR)
|
||||||
|
VPATH += $(dir $(wildcard ../$(BDKDIR)/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/))
|
||||||
|
|
||||||
|
# Main and graphics.
|
||||||
|
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||||
|
start.o loader.o lz.o \
|
||||||
|
)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
CUSTOMDEFINES := -DBL_MAGIC=$(IPL_MAGIC)
|
||||||
|
CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -DBL_VER_HF=$(BLVERSION_HOTFX) -DBL_RESERVED=$(BLVERSION_RSVD)
|
||||||
|
|
||||||
|
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
|
||||||
|
WARNINGS := -Wall -Wno-array-bounds -Wno-stringop-overflow
|
||||||
|
|
||||||
|
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
|
||||||
|
CFLAGS = $(ARCH) -O2 -g -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
|
||||||
|
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=LDR_LOAD_ADDR=$(LDR_LOAD_ADDR)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
all: $(TARGET).bin $(TOOLSLZ) $(TOOLSB2C)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -rf $(OBJS)
|
||||||
|
|
||||||
|
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
||||||
|
$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$(PAYLOAD_NAME).bin
|
||||||
|
|
||||||
|
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||||
|
@$(CC) $(LDFLAGS) -T link.ld $^ -o $@
|
||||||
|
|
||||||
|
$(BUILDDIR)/$(TARGET)/%.o: %.c
|
||||||
|
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||||
|
|
||||||
|
$(BUILDDIR)/$(TARGET)/%.o: %.S
|
||||||
|
@$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(OBJS): $(BUILDDIR)/$(TARGET)
|
||||||
|
|
||||||
|
$(BUILDDIR)/$(TARGET):
|
||||||
|
@mkdir -p "$(BUILDDIR)"
|
||||||
|
@mkdir -p "$(BUILDDIR)/$(TARGET)"
|
||||||
|
@mkdir -p "$(OUTPUTDIR)"
|
||||||
20
loader/link.ld
Normal file
20
loader/link.ld
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
PROVIDE(__ipl_start = LDR_LOAD_ADDR);
|
||||||
|
. = __ipl_start;
|
||||||
|
.text : {
|
||||||
|
*(.text._start);
|
||||||
|
KEEP(*(._boot_cfg));
|
||||||
|
*(.text*);
|
||||||
|
}
|
||||||
|
.data : {
|
||||||
|
*(.data*);
|
||||||
|
*(.rodata*);
|
||||||
|
*(._payload_00);
|
||||||
|
*(._payload_01);
|
||||||
|
}
|
||||||
|
__ldr_end = .;
|
||||||
|
. = ALIGN(0x10);
|
||||||
|
__ipl_end = .;
|
||||||
|
}
|
||||||
81
loader/loader.c
Normal file
81
loader/loader.c
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 CTCaer
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "payload_00.h"
|
||||||
|
#include "payload_01.h"
|
||||||
|
|
||||||
|
#include <memory_map.h>
|
||||||
|
#include <libs/compr/lz.h>
|
||||||
|
#include <soc/clock.h>
|
||||||
|
#include <soc/t210.h>
|
||||||
|
|
||||||
|
// 0x4003D000: Safe for panic preserving, 0x40038000: Safe for debugging needs.
|
||||||
|
#define IPL_RELOC_TOP 0x40038000
|
||||||
|
#define IPL_PATCHED_RELOC_SZ 0x94
|
||||||
|
|
||||||
|
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
|
||||||
|
|
||||||
|
void loader_main()
|
||||||
|
{
|
||||||
|
// Preliminary BPMP clocks init.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10; // Set HCLK div to 2 and PCLK div to 1.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set SCLK div to 1.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set clk source to Run and PLLP_OUT2 (204MHz).
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; // Enable SUPER_SDIV to 1.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
|
||||||
|
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz).
|
||||||
|
|
||||||
|
// Get Loader and Payload size.
|
||||||
|
u32 payload_size = sizeof(payload_00) + sizeof(payload_01); // Actual payload size.
|
||||||
|
payload_size += (u32)payload_01 - (u32)payload_00 - sizeof(payload_00); // Add array alignment.
|
||||||
|
u32 *payload_addr = (u32 *)payload_00;
|
||||||
|
|
||||||
|
// Relocate payload to a safer place.
|
||||||
|
u32 bytes = ALIGN(payload_size, 4) >> 2;
|
||||||
|
u32 *addr = payload_addr + bytes - 1;
|
||||||
|
u32 *dst = (u32 *)(IPL_RELOC_TOP - 4);
|
||||||
|
while (bytes)
|
||||||
|
{
|
||||||
|
*dst = *addr;
|
||||||
|
dst--;
|
||||||
|
addr--;
|
||||||
|
bytes--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set source address of the first part.
|
||||||
|
u8 *src_addr = (void *)(IPL_RELOC_TOP - ALIGN(payload_size, 4));
|
||||||
|
// Uncompress first part.
|
||||||
|
u32 dst_pos = LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR, sizeof(payload_00));
|
||||||
|
|
||||||
|
// Set source address of the second part. Includes array alignment.
|
||||||
|
src_addr += (u32)payload_01 - (u32)payload_00;
|
||||||
|
// Uncompress second part.
|
||||||
|
LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR + dst_pos, sizeof(payload_01));
|
||||||
|
|
||||||
|
// Copy over boot configuration storage.
|
||||||
|
memcpy((u8 *)(IPL_LOAD_ADDR + IPL_PATCHED_RELOC_SZ), &b_cfg, sizeof(boot_cfg_t));
|
||||||
|
|
||||||
|
// Chainload into uncompressed payload.
|
||||||
|
void (*ipl_ptr)() = (void *)IPL_LOAD_ADDR;
|
||||||
|
(*ipl_ptr)();
|
||||||
|
|
||||||
|
// Halt if we managed to get out of execution.
|
||||||
|
while (true)
|
||||||
|
;
|
||||||
|
}
|
||||||
73
loader/start.S
Normal file
73
loader/start.S
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 naehrwert
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section .text._start
|
||||||
|
.arm
|
||||||
|
|
||||||
|
.extern _reloc_ipl
|
||||||
|
.type _reloc_ipl, %function
|
||||||
|
|
||||||
|
.extern memset
|
||||||
|
.type memset, %function
|
||||||
|
|
||||||
|
.extern loader_main
|
||||||
|
.type loader_main, %function
|
||||||
|
|
||||||
|
.globl _start
|
||||||
|
.type _start, %function
|
||||||
|
_start:
|
||||||
|
ADR R0, _start
|
||||||
|
LDR R1, =__ipl_start
|
||||||
|
CMP R0, R1
|
||||||
|
BEQ _real_start
|
||||||
|
|
||||||
|
/* If we are not in the right location already, copy a relocator to upper IRAM. */
|
||||||
|
ADR R2, _reloc_ipl
|
||||||
|
LDR R3, =0x4003FF00
|
||||||
|
MOV R4, #(_real_start - _reloc_ipl)
|
||||||
|
_copy_loop:
|
||||||
|
LDMIA R2!, {R5}
|
||||||
|
STMIA R3!, {R5}
|
||||||
|
SUBS R4, #4
|
||||||
|
BNE _copy_loop
|
||||||
|
|
||||||
|
/* Use the relocator to copy ourselves into the right place. */
|
||||||
|
LDR R2, =__ipl_end
|
||||||
|
SUB R2, R2, R1
|
||||||
|
LDR R3, =_real_start
|
||||||
|
LDR R4, =0x4003FF00
|
||||||
|
BX R4
|
||||||
|
|
||||||
|
_reloc_ipl:
|
||||||
|
LDMIA R0!, {R4-R7}
|
||||||
|
STMIA R1!, {R4-R7}
|
||||||
|
SUBS R2, #0x10
|
||||||
|
BNE _reloc_ipl
|
||||||
|
/* Jump to the relocated entry. */
|
||||||
|
BX R3
|
||||||
|
|
||||||
|
_real_start:
|
||||||
|
/* Initially, we place our stack in IRAM but will move it to SDRAM later. */
|
||||||
|
LDR SP, =0x40007000
|
||||||
|
LDR R0, =__ldr_end
|
||||||
|
BL loader_main
|
||||||
|
B .
|
||||||
|
.word 0
|
||||||
|
.word 0
|
||||||
|
.word 0
|
||||||
|
.word 0
|
||||||
|
.word 0
|
||||||
|
.word 0
|
||||||
54
scripts/FirmwareDump.te
Normal file
54
scripts/FirmwareDump.te
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#REQUIRE KEYS
|
||||||
|
#REQUIRE SD
|
||||||
|
p=println
|
||||||
|
pe={pause() exit()}
|
||||||
|
fwstr={fw=maj.str()+"."+min.str()+"."+pat.str()}
|
||||||
|
fv={a=readsave("bis:/save/8000000000000120")
|
||||||
|
b=a.read("/meta/imkvdb.arc")
|
||||||
|
c=["BYTE[]",9,8,0,0,0,0,0,1]
|
||||||
|
d=b.find(c)
|
||||||
|
if(d>0){
|
||||||
|
e=b.slice(d+8,4).project()
|
||||||
|
ver=(e[3]<<24)|(e[2]<<16)|(e[1]<<8)|(e[0])
|
||||||
|
pat=((ver>>16)&((1<<4)- 1))
|
||||||
|
min=((ver>>20)&((1<<6)- 1))
|
||||||
|
maj=((ver>>26)&((1<<6)- 1))
|
||||||
|
}.else(){print("Fw not found")pe()}
|
||||||
|
a=0 fwstr()}
|
||||||
|
if(mountsys("SYSTEM")){print("SYSTEM MOUNT FAIL")pe()}
|
||||||
|
fv()
|
||||||
|
sysfw=fw
|
||||||
|
p("Sys' fw is",fw)
|
||||||
|
emufw=""
|
||||||
|
if (emu()){if(!mountemu("SYSTEM")){fv()emufw=fw p("Emu's fw is",fw)}}
|
||||||
|
op=["Exit","Dump sysmmc"].copy()
|
||||||
|
if (emufw!=""){op+"Dump emummc"}
|
||||||
|
p()r=menu(op,0)clear()
|
||||||
|
if(r==0){exit()}
|
||||||
|
if(r==1){fw=sysfw if(mountsys("SYSTEM")){print("SYSTEM MOUNT FAIL")pe()}}
|
||||||
|
if(r==2){fw=emufw if(mountemu("SYSTEM")){print("SYSTEM MOUNT FAIL")pe()}}
|
||||||
|
mkdir("sd:/tegraexplorer")
|
||||||
|
mkdir("sd:/tegraexplorer/Firmware")
|
||||||
|
bsp="sd:/tegraexplorer/Firmware/"+fw
|
||||||
|
if(fsexists(bsp)){p("Dir already exists! Press power to replace, any other key to exit") a=pause() if(!a.power){exit()} deldir(bsp)}
|
||||||
|
mkdir(bsp)
|
||||||
|
p("Dumping to",bsp)
|
||||||
|
con=readdir("bis:/Contents/registered")
|
||||||
|
if(con.result!=0){println("Fail reading dir")pe()}
|
||||||
|
c=(con.files.len()+con.folders.len()).str()
|
||||||
|
i=1 f=0 t=timer()
|
||||||
|
dump={
|
||||||
|
fi.foreach("x"){
|
||||||
|
if(f){fp="bis:/Contents/registered/"+x+"/00"}
|
||||||
|
.else(){fp="bis:/Contents/registered/"+x}
|
||||||
|
name=x
|
||||||
|
if(ncatype(fp)==1){name=name- 4+".cnmt.nca"}
|
||||||
|
color(0x00FF00)
|
||||||
|
print("\r["+i.str()+"/"+c+"]", x)
|
||||||
|
if(copyfile(fp,bsp+"/"+name)){println("\nErr during copy")pe()}
|
||||||
|
i=i+1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fi=con.files dump()
|
||||||
|
f=1 fi=con.folders dump()
|
||||||
|
p("\nDone! Took",timer()-t/1000,"s")pause()
|
||||||
31
scripts/SystemWipe.te
Normal file
31
scripts/SystemWipe.te
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#REQUIRE KEYS
|
||||||
|
is=["8000000000000120","80000000000000d1","8000000000000047"]
|
||||||
|
p=println
|
||||||
|
pr=print
|
||||||
|
pe={pause() exit()}
|
||||||
|
wait={t=timer()while(timer()<(t+tw)){print("Wait for",(t+tw-timer()/1000),"seconds \r")}}
|
||||||
|
p("System wiper\n")
|
||||||
|
op=["Exit","Wipe sysmmc"].copy()
|
||||||
|
if (emu()){op+"Wipe emummc"}
|
||||||
|
r=menu(op,0)clear()
|
||||||
|
if(r==0){exit()}
|
||||||
|
if(r==1){p("Selected sysmmc")mount=mountsys}
|
||||||
|
if(r==2){p("Selected emummc")mount=mountemu}
|
||||||
|
if(mount("SYSTEM")){p("Mount failed!")pe()}
|
||||||
|
color(0xFF0000)
|
||||||
|
p("Are you sure you want to wipe everything?\nThis includes:\n- Saves\n- Game Data\n- All other data on the system\n\nUse this only as a last resort!")
|
||||||
|
color(0xFFFF00)
|
||||||
|
tw=10000
|
||||||
|
wait()
|
||||||
|
color(0x0000FF)
|
||||||
|
p("Press power to wipe, any other key to exit")a=pause()if(!a.power){exit()}clear()
|
||||||
|
color(0xFF0000)
|
||||||
|
pr("Deleting system saves... ")
|
||||||
|
f=readdir("bis:/save")
|
||||||
|
if(f.folders.len()!=0){p("Folders in save dir???")pe()}
|
||||||
|
f.files.foreach("x"){if(!is.contains(x)){if(delfile("bis:/save/"+x)){p("File deletion failed: ", x)pe()}}}
|
||||||
|
pr("Done!\nDeleting user dirs...")ud=["Album","Contents","save","saveMeta","temp"]
|
||||||
|
if(mount("USER")){p("Mount failed!")pe()}
|
||||||
|
ud.foreach("x"){pr("\n"+x,"")if(deldir("bis:/"+x)){p("Dir deletion failed")pe()}mkdir("bis:/"+x)}
|
||||||
|
mkdir("bis:/Contents/placehld")mkdir("bis:/Contents/registered")
|
||||||
|
color(0x00FF00)p("\n\nDone!")pause()
|
||||||
@@ -12,7 +12,7 @@ char *CombinePaths(const char *current, const char *add){
|
|||||||
size_t size = strlen(current) + strlen(add) + 2;
|
size_t size = strlen(current) + strlen(add) + 2;
|
||||||
ret = (char*) malloc (size);
|
ret = (char*) malloc (size);
|
||||||
|
|
||||||
sprintf(ret, (current[strlen(current) - 1] == '/') ? "%s%s" : "%s/%s", current, add);
|
s_printf(ret, (current[strlen(current) - 1] == '/') ? "%s%s" : "%s/%s", current, add);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -47,6 +47,7 @@ char *GetFileAttribs(FSEntry_t entry){
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns 1 if a file exists, 0 if it does not
|
||||||
bool FileExists(const char* path){
|
bool FileExists(const char* path){
|
||||||
FRESULT fr;
|
FRESULT fr;
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ void FileExplorer(char *path){
|
|||||||
res = 0;
|
res = 0;
|
||||||
|
|
||||||
res = newMenu(&entries, res, 60, 42, ENABLEB | ENABLEPAGECOUNT, (int)fileVec.count);
|
res = newMenu(&entries, res, 60, 42, ENABLEB | ENABLEPAGECOUNT, (int)fileVec.count);
|
||||||
|
vecFree(entries);
|
||||||
|
|
||||||
char *oldPath = storedPath;
|
char *oldPath = storedPath;
|
||||||
|
|
||||||
@@ -125,6 +126,7 @@ void FileExplorer(char *path){
|
|||||||
else if (res < ARR_LEN(topEntries)) {
|
else if (res < ARR_LEN(topEntries)) {
|
||||||
if (!strcmp(storedPath, path)){
|
if (!strcmp(storedPath, path)){
|
||||||
clearFileVector(&fileVec);
|
clearFileVector(&fileVec);
|
||||||
|
free(storedPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../../utils/vector.h"
|
#include "../../utils/vector.h"
|
||||||
|
#include "../../gfx/menu.h"
|
||||||
|
#include "../fstypes.h"
|
||||||
|
|
||||||
void FileExplorer(char *path);
|
void FileExplorer(char *path);
|
||||||
|
MenuEntry_t MakeMenuOutFSEntry(FSEntry_t entry);
|
||||||
@@ -11,11 +11,12 @@
|
|||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
#include "../../utils/utils.h"
|
#include "../../utils/utils.h"
|
||||||
#include "../../keys/nca.h"
|
#include "../../keys/nca.h"
|
||||||
#include "../../script/lexer.h"
|
|
||||||
#include "../../script/parser.h"
|
|
||||||
#include "../../script/variables.h"
|
|
||||||
#include <storage/nx_sd.h>
|
#include <storage/nx_sd.h>
|
||||||
#include "../../storage/emummc.h"
|
#include "../../storage/emummc.h"
|
||||||
|
#include "../../script/eval.h"
|
||||||
|
#include "../../script/parser.h"
|
||||||
|
#include "../../script/garbageCollector.h"
|
||||||
|
|
||||||
|
|
||||||
MenuEntry_t FileMenuEntries[] = {
|
MenuEntry_t FileMenuEntries[] = {
|
||||||
{.optionUnion = COLORTORGB(COLOR_WHITE) | SKIPBIT, .name = "-- File menu --"},
|
{.optionUnion = COLORTORGB(COLOR_WHITE) | SKIPBIT, .name = "-- File menu --"},
|
||||||
@@ -71,29 +72,45 @@ void DeleteFile(char *path, FSEntry_t entry){
|
|||||||
free(thing);
|
free(thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RunScriptString(char *str, u32 size){
|
||||||
|
TConf.scriptCWD = "sd:/";
|
||||||
|
gfx_clearscreen();
|
||||||
|
ParserRet_t ret = parseScript(str, size);
|
||||||
|
setStaticVars(&ret.staticVarHolder);
|
||||||
|
initRuntimeVars();
|
||||||
|
eval(ret.main.operations.data, ret.main.operations.count, 0);
|
||||||
|
exitRuntimeVars();
|
||||||
|
exitStaticVars(&ret.staticVarHolder);
|
||||||
|
exitFunction(ret.main.operations.data, ret.main.operations.count);
|
||||||
|
vecFree(ret.staticVarHolder);
|
||||||
|
vecFree(ret.main.operations);
|
||||||
|
}
|
||||||
|
|
||||||
void RunScript(char *path, FSEntry_t entry){
|
void RunScript(char *path, FSEntry_t entry){
|
||||||
char *thing = CombinePaths(path, entry.name);
|
char *thing = CombinePaths(path, entry.name);
|
||||||
u32 size;
|
u32 size;
|
||||||
char *script = sd_file_read(thing, &size);
|
char *script = sd_file_read(thing, &size);
|
||||||
free(thing);
|
free(thing);
|
||||||
|
TConf.scriptCWD = path;
|
||||||
|
|
||||||
if (!script)
|
if (!script)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (((entry.size >= 64 && entry.sizeDef == 1) || entry.sizeDef >= 2) && !TConf.minervaEnabled)
|
if (((entry.size >= 16 && entry.sizeDef == 1) || entry.sizeDef >= 2) && !TConf.minervaEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gfx_clearscreen();
|
gfx_clearscreen();
|
||||||
scriptCtx_t ctx = createScriptCtx();
|
|
||||||
ctx.script = runLexer(script, size);
|
ParserRet_t ret = parseScript(script, size);
|
||||||
free(script);
|
free(script);
|
||||||
|
setStaticVars(&ret.staticVarHolder);
|
||||||
dictVectorAdd(&ctx.varDict, newDict(CpyStr("_CWD"), (newVar(StringType, 0, .stringType = path))));
|
initRuntimeVars();
|
||||||
dictVectorAdd(&ctx.varDict, newDict(CpyStr("_EMU"), (newVar(IntType, 0, emu_cfg.enabled))));
|
Variable_t* res = eval(ret.main.operations.data, ret.main.operations.count, 1);
|
||||||
|
exitRuntimeVars();
|
||||||
printError(mainLoop(&ctx));
|
exitStaticVars(&ret.staticVarHolder);
|
||||||
|
exitFunction(ret.main.operations.data, ret.main.operations.count);
|
||||||
freeDictVector(&ctx.varDict);
|
vecFree(ret.staticVarHolder);
|
||||||
lexarVectorClear(&ctx.script);
|
vecFree(ret.main.operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenameFile(char *path, FSEntry_t entry){
|
void RenameFile(char *path, FSEntry_t entry){
|
||||||
@@ -130,7 +147,7 @@ void HexView(char *path, FSEntry_t entry){
|
|||||||
hidRead();
|
hidRead();
|
||||||
|
|
||||||
gfx_clearscreen();
|
gfx_clearscreen();
|
||||||
print = malloc(2048);
|
print = calloc(2048, 1);
|
||||||
|
|
||||||
if ((res = f_open(&in, filePath, FA_READ | FA_OPEN_EXISTING))){
|
if ((res = f_open(&in, filePath, FA_READ | FA_OPEN_EXISTING))){
|
||||||
DrawError(newErrCode(res));
|
DrawError(newErrCode(res));
|
||||||
@@ -146,7 +163,7 @@ void HexView(char *path, FSEntry_t entry){
|
|||||||
}
|
}
|
||||||
|
|
||||||
gfx_con_setpos(0, 31);
|
gfx_con_setpos(0, 31);
|
||||||
gfx_hexdump(offset * 32, print, size);
|
gfx_hexdump(offset * 32, print, ((size + 31) / 32) * 32);
|
||||||
|
|
||||||
input = hidRead();
|
input = hidRead();
|
||||||
|
|
||||||
@@ -180,7 +197,7 @@ void FileMenu(char *path, FSEntry_t entry){
|
|||||||
FileMenuEntries[0].sizeUnion = entry.sizeUnion;
|
FileMenuEntries[0].sizeUnion = entry.sizeUnion;
|
||||||
char attribs[16];
|
char attribs[16];
|
||||||
char *attribList = GetFileAttribs(entry);
|
char *attribList = GetFileAttribs(entry);
|
||||||
sprintf(attribs, "Attribs:%s\n", attribList);
|
s_printf(attribs, "Attribs:%s\n", attribList);
|
||||||
free(attribList);
|
free(attribList);
|
||||||
FileMenuEntries[2].name = attribs;
|
FileMenuEntries[2].name = attribs;
|
||||||
|
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ typedef void (*fileMenuPath)(char *path, FSEntry_t entry);
|
|||||||
|
|
||||||
void FileMenu(char *path, FSEntry_t entry);
|
void FileMenu(char *path, FSEntry_t entry);
|
||||||
void RunScript(char *path, FSEntry_t entry);
|
void RunScript(char *path, FSEntry_t entry);
|
||||||
|
void RunScriptString(char *str, u32 size);
|
||||||
@@ -11,9 +11,6 @@
|
|||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
#include "../../utils/utils.h"
|
#include "../../utils/utils.h"
|
||||||
#include "../../keys/nca.h"
|
#include "../../keys/nca.h"
|
||||||
#include "../../script/lexer.h"
|
|
||||||
#include "../../script/parser.h"
|
|
||||||
#include "../../script/variables.h"
|
|
||||||
#include <storage/nx_sd.h>
|
#include <storage/nx_sd.h>
|
||||||
#include "../fscopy.h"
|
#include "../fscopy.h"
|
||||||
|
|
||||||
@@ -114,7 +111,7 @@ int FolderMenu(const char *path){
|
|||||||
|
|
||||||
char attribs[16];
|
char attribs[16];
|
||||||
char *attribList = GetFileAttribs(file);
|
char *attribList = GetFileAttribs(file);
|
||||||
sprintf(attribs, "Attribs:%s\n", attribList);
|
s_printf(attribs, "Attribs:%s\n", attribList);
|
||||||
free(attribList);
|
free(attribList);
|
||||||
FolderMenuEntries[2].name = attribs;
|
FolderMenuEntries[2].name = attribs;
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ int newMenu(Vector_t* vec, int startIndex, int screenLenX, int screenLenY, u8 op
|
|||||||
if (options & ENABLEPAGECOUNT){
|
if (options & ENABLEPAGECOUNT){
|
||||||
SETCOLOR(COLOR_DEFAULT, COLOR_WHITE);
|
SETCOLOR(COLOR_DEFAULT, COLOR_WHITE);
|
||||||
char temp[40] = "";
|
char temp[40] = "";
|
||||||
sprintf(temp, " Page %d / %d | Total %d entries", (selected / screenLenY) + 1, ((vec->count - 1) / screenLenY) + 1, entryCount);
|
s_printf(temp, " Page %d / %d | Total %d entries", (selected / screenLenY) + 1, ((vec->count - 1) / screenLenY) + 1, entryCount);
|
||||||
gfx_con_setpos(YLEFT - strlen(temp) * 18, 0);
|
gfx_con_setpos(YLEFT - strlen(temp) * 18, 0);
|
||||||
gfx_printf(temp);
|
gfx_printf(temp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,29 +23,48 @@
|
|||||||
#include <sec/se.h>
|
#include <sec/se.h>
|
||||||
|
|
||||||
static const pkg1_id_t _pkg1_ids[] = {
|
static const pkg1_id_t _pkg1_ids[] = {
|
||||||
{ "20161121183008", 0 }, //1.0.0
|
{ "20161121", 0 }, //1.0.0
|
||||||
{ "20170210155124", 0 }, //2.0.0 - 2.3.0
|
{ "20170210", 0 }, //2.0.0 - 2.3.0
|
||||||
{ "20170519101410", 1 }, //3.0.0
|
{ "20170519", 1 }, //3.0.0
|
||||||
{ "20170710161758", 2 }, //3.0.1 - 3.0.2
|
{ "20170710", 2 }, //3.0.1 - 3.0.2
|
||||||
{ "20170921172629", 3 }, //4.0.0 - 4.1.0
|
{ "20170921", 3 }, //4.0.0 - 4.1.0
|
||||||
{ "20180220163747", 4 }, //5.0.0 - 5.1.0
|
{ "20180220", 4 }, //5.0.0 - 5.1.0
|
||||||
{ "20180802162753", 5 }, //6.0.0 - 6.1.0
|
{ "20180802", 5 }, //6.0.0 - 6.1.0
|
||||||
{ "20181107105733", 6 }, //6.2.0
|
{ "20181107", 6 }, //6.2.0
|
||||||
{ "20181218175730", 7 }, //7.0.0
|
{ "20181218", 7 }, //7.0.0
|
||||||
{ "20190208150037", 7 }, //7.0.1
|
{ "20190208", 7 }, //7.0.1
|
||||||
{ "20190314172056", 7 }, //8.0.0 - 8.0.1
|
{ "20190314", 7 }, //8.0.0 - 8.0.1
|
||||||
{ "20190531152432", 8 }, //8.1.0
|
{ "20190531", 8 }, //8.1.0 - 8.1.1
|
||||||
{ "20190809135709", 9 }, //9.0.0 - 9.0.1
|
{ "20190809", 9 }, //9.0.0 - 9.0.1
|
||||||
{ "20191021113848", 10}, //9.1.0
|
{ "20191021", 10}, //9.1.0 - 9.2.0
|
||||||
{ "20200303104606", 10}, //10.0.0 - 10.2.0
|
{ "20200303", 10}, //10.0.0 - 10.2.0
|
||||||
{ "20201030110855", 10}, //11.0.0
|
{ "20201030", 10}, //11.0.0 - 11.0.1
|
||||||
|
{ "20210129", 10}, //12.0.0 - 12.0.1
|
||||||
|
{ "20210422", 10}, //12.0.2 - 12.0.3
|
||||||
|
{ "20210607", 11}, //12.1.0
|
||||||
|
{ "20210805", 12}, //13.0.0 - 13.2.0
|
||||||
|
{ "20220105", 12}, //13.2.1
|
||||||
|
{ "20220209", 13}, //14.0.0 - 14.1.2
|
||||||
|
{ "20220801", 14}, //15.0.0 - 15.0.1
|
||||||
|
{ "20230111", 15}, //16.0.0+
|
||||||
{ NULL } //End.
|
{ NULL } //End.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define KB_FIRMWARE_VERSION_MAX 11
|
||||||
|
|
||||||
const pkg1_id_t *pkg1_identify(u8 *pkg1)
|
const pkg1_id_t *pkg1_identify(u8 *pkg1)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; _pkg1_ids[i].id; i++)
|
for (u32 i = 0; _pkg1_ids[i].id; i++)
|
||||||
if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8))
|
if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8))
|
||||||
return &_pkg1_ids[i];
|
return &_pkg1_ids[i];
|
||||||
return NULL;
|
|
||||||
|
char build_date[15];
|
||||||
|
memcpy(build_date, (char *)(pkg1 + 0x10), 14);
|
||||||
|
build_date[14] = 0;
|
||||||
|
|
||||||
|
if (*(pkg1 + 0xE) != KB_FIRMWARE_VERSION_MAX + 1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &_pkg1_ids[ARRAY_SIZE(_pkg1_ids)-1];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,7 +240,10 @@ static ALWAYS_INLINE u8 *_read_pkg1(const pkg1_id_t **pkg1_id) {
|
|||||||
*pkg1_id = pkg1_identify(pkg1 + pk1_offset);
|
*pkg1_id = pkg1_identify(pkg1 + pk1_offset);
|
||||||
if (!*pkg1_id) {
|
if (!*pkg1_id) {
|
||||||
DPRINTF("Unknown pkg1 version.\n Make sure you have the latest Lockpick_RCM.\n If a new firmware version just came out,\n Lockpick_RCM must be updated.\n Check Github for new release.");
|
DPRINTF("Unknown pkg1 version.\n Make sure you have the latest Lockpick_RCM.\n If a new firmware version just came out,\n Lockpick_RCM must be updated.\n Check Github for new release.");
|
||||||
gfx_hexdump(0, pkg1, 0x20);
|
//gfx_hexdump(0, pkg1 + pk1_offset, 0x20);
|
||||||
|
char pkg1txt[16] = {0};
|
||||||
|
memcpy(pkg1txt, pkg1 + pk1_offset + 0x10, 14);
|
||||||
|
gfx_printf("Unknown pkg1 version\nMake sure you have the latest version of TegraExplorer\n\nPKG1: '%s'\n", pkg1txt);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
91
source/script/ABadIdeaVersion3.c
Normal file
91
source/script/ABadIdeaVersion3.c
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "compat.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "intClass.h"
|
||||||
|
#include "StringClass.h"
|
||||||
|
#include "eval.h"
|
||||||
|
#include "garbageCollector.h"
|
||||||
|
|
||||||
|
// TODO: error handling DONE
|
||||||
|
// TODO: unsolved arrays
|
||||||
|
// TODO: free-ing vars & script at end
|
||||||
|
// TODO: implement functions from tsv2
|
||||||
|
// TODO: add len to string
|
||||||
|
// TODO: clear old int values from array DONE
|
||||||
|
// TODO: int and str should be statically included in OP_t DONE
|
||||||
|
|
||||||
|
char* readFile(char* path) {
|
||||||
|
FILE* fp = fopen(path, "r");
|
||||||
|
if (fp == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fseek(fp, 0L, SEEK_END);
|
||||||
|
size_t size = ftell(fp);
|
||||||
|
fseek(fp, 0L, SEEK_SET);
|
||||||
|
|
||||||
|
char* ret = calloc(size + 1, 1);
|
||||||
|
fread(ret, size, 1, fp);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
//gfx_printf("Hello world!\n");
|
||||||
|
|
||||||
|
//StartParse("a b c de 0x1 0x10 \"yeet\" + + ");
|
||||||
|
/*
|
||||||
|
Variable_t b = newStringVariable("Hello world\n", 1, 0);
|
||||||
|
callClass("__print__", &b, NULL, NULL);
|
||||||
|
|
||||||
|
Variable_t a = newIntVariable(69, 0);
|
||||||
|
Variable_t c = newIntVariable(1, 0);
|
||||||
|
Variable_t e = newStringVariable("snake", 1, 0);
|
||||||
|
Vector_t fuk = newVec(sizeof(Variable_t), 1);
|
||||||
|
vecAdd(&fuk, c);
|
||||||
|
Variable_t *d = callClass("+", &a, NULL, &fuk);
|
||||||
|
callClass("__print__", d, NULL, NULL);
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Vector_t v = newVec(sizeof(int), 4);
|
||||||
|
int a = 69;
|
||||||
|
vecAdd(&v, a);
|
||||||
|
vecAdd(&v, a);
|
||||||
|
vecAdd(&v, a);
|
||||||
|
vecAdd(&v, a);
|
||||||
|
|
||||||
|
vecForEach(int*, b, (&v))
|
||||||
|
printf("%d\n", *b);
|
||||||
|
|
||||||
|
return;
|
||||||
|
*/
|
||||||
|
char* script = readFile("input.te");
|
||||||
|
if (script == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//parseScript("#REQUIRE VER 3.0.5\nmain = { two = 1 + 1 }");
|
||||||
|
//ParserRet_t ret = parseScript("a.b.c(1){ a.b.c() }");
|
||||||
|
//while (1) {
|
||||||
|
ParserRet_t ret = parseScript(script, strlen(script));
|
||||||
|
|
||||||
|
|
||||||
|
setStaticVars(&ret.staticVarHolder);
|
||||||
|
initRuntimeVars();
|
||||||
|
|
||||||
|
Variable_t* res = eval(ret.main.operations.data, ret.main.operations.count, 1);
|
||||||
|
|
||||||
|
exitRuntimeVars();
|
||||||
|
exitStaticVars(&ret.staticVarHolder);
|
||||||
|
exitFunction(ret.main.operations.data, ret.main.operations.count);
|
||||||
|
vecFree(ret.staticVarHolder);
|
||||||
|
vecFree(ret.main.operations);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
free(script);
|
||||||
|
gfx_printf("done");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
188
source/script/ABadIdeaVersion3.vcxproj
Normal file
188
source/script/ABadIdeaVersion3.vcxproj
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{b4ea4793-03fc-4c25-b69b-a5fbad2d89d5}</ProjectGuid>
|
||||||
|
<RootNamespace>ABadIdeaVersion3</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<EnableASAN>false</EnableASAN>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<Optimization>MinSpace</Optimization>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="ABadIdeaVersion3.c" />
|
||||||
|
<ClCompile Include="arrayClass.c" />
|
||||||
|
<ClCompile Include="arrayReferenceClass.c" />
|
||||||
|
<ClCompile Include="dictionaryClass.c" />
|
||||||
|
<ClCompile Include="else.c" />
|
||||||
|
<ClCompile Include="eval.c" />
|
||||||
|
<ClCompile Include="functionClass.c" />
|
||||||
|
<ClCompile Include="garbageCollector.c" />
|
||||||
|
<ClCompile Include="genericClass.c" />
|
||||||
|
<ClCompile Include="intClass.c" />
|
||||||
|
<ClCompile Include="model.c" />
|
||||||
|
<ClCompile Include="parser.c" />
|
||||||
|
<ClCompile Include="scriptError.c" />
|
||||||
|
<ClCompile Include="standardLibrary.c" />
|
||||||
|
<ClCompile Include="StringClass.c" />
|
||||||
|
<ClCompile Include="unsolvedArrayClass.c" />
|
||||||
|
<ClCompile Include="vector.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="arrayClass.h" />
|
||||||
|
<ClInclude Include="arrayReferenceClass.h" />
|
||||||
|
<ClInclude Include="compat.h" />
|
||||||
|
<ClInclude Include="dictionaryClass.h" />
|
||||||
|
<ClInclude Include="else.h" />
|
||||||
|
<ClInclude Include="eval.h" />
|
||||||
|
<ClInclude Include="functionClass.h" />
|
||||||
|
<ClInclude Include="garbageCollector.h" />
|
||||||
|
<ClInclude Include="genericClass.h" />
|
||||||
|
<ClInclude Include="intClass.h" />
|
||||||
|
<ClInclude Include="model.h" />
|
||||||
|
<ClInclude Include="parser.h" />
|
||||||
|
<ClInclude Include="scriptError.h" />
|
||||||
|
<ClInclude Include="standardLibrary.h" />
|
||||||
|
<ClInclude Include="StringClass.h" />
|
||||||
|
<ClInclude Include="unsolvedArrayClass.h" />
|
||||||
|
<ClInclude Include="vector.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="input.te" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
152
source/script/ABadIdeaVersion3.vcxproj.filters
Normal file
152
source/script/ABadIdeaVersion3.vcxproj.filters
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Classes">
|
||||||
|
<UniqueIdentifier>{c245ac36-a649-432b-a663-98ff9d02d3f4}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Classes\String">
|
||||||
|
<UniqueIdentifier>{e4d90dab-a1e0-4a27-82a1-dc2c6b81f0bd}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Classes\Generic">
|
||||||
|
<UniqueIdentifier>{1aacfe02-949c-4394-b408-28d73d702918}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Classes\Array">
|
||||||
|
<UniqueIdentifier>{5878f4a8-cac0-40aa-8866-6109bf6688ab}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Classes\Dictionary">
|
||||||
|
<UniqueIdentifier>{ec7391f8-d60e-46eb-965e-c2d84d48d784}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Classes\Function">
|
||||||
|
<UniqueIdentifier>{015ca379-a813-4d13-a929-3b0efe72bb02}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Classes\Int">
|
||||||
|
<UniqueIdentifier>{64738969-63b9-4d0e-85b9-d9a63a7e36b3}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Classes\Elseable">
|
||||||
|
<UniqueIdentifier>{ba83a808-23f1-44c6-85e4-d0c6c77200fa}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="ABadIdeaVersion3.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vector.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="parser.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="model.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="eval.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="genericClass.c">
|
||||||
|
<Filter>Source Files\Classes\Generic</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="garbageCollector.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="functionClass.c">
|
||||||
|
<Filter>Source Files\Classes\Function</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="StringClass.c">
|
||||||
|
<Filter>Source Files\Classes\String</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="unsolvedArrayClass.c">
|
||||||
|
<Filter>Source Files\Classes\Array</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="arrayClass.c">
|
||||||
|
<Filter>Source Files\Classes\Array</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="intClass.c">
|
||||||
|
<Filter>Source Files\Classes\Int</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="arrayReferenceClass.c">
|
||||||
|
<Filter>Source Files\Classes\Array</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="standardLibrary.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="scriptError.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="else.c">
|
||||||
|
<Filter>Source Files\Classes\Elseable</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="dictionaryClass.c">
|
||||||
|
<Filter>Source Files\Classes\Dictionary</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="compat.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="model.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vector.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="parser.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="eval.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="garbageCollector.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="dictionaryClass.h">
|
||||||
|
<Filter>Source Files\Classes\Dictionary</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="arrayClass.h">
|
||||||
|
<Filter>Source Files\Classes\Array</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="intClass.h">
|
||||||
|
<Filter>Source Files\Classes\Int</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="StringClass.h">
|
||||||
|
<Filter>Source Files\Classes\String</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="unsolvedArrayClass.h">
|
||||||
|
<Filter>Source Files\Classes\Array</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="functionClass.h">
|
||||||
|
<Filter>Source Files\Classes\Function</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="genericClass.h">
|
||||||
|
<Filter>Source Files\Classes\Generic</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="arrayReferenceClass.h">
|
||||||
|
<Filter>Source Files\Classes\Array</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="standardLibrary.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="scriptError.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="else.h">
|
||||||
|
<Filter>Source Files\Classes\Elseable</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="input.te">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
4
source/script/ABadIdeaVersion3.vcxproj.user
Normal file
4
source/script/ABadIdeaVersion3.vcxproj.user
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup />
|
||||||
|
</Project>
|
||||||
132
source/script/StringClass.c
Normal file
132
source/script/StringClass.c
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
#include "StringClass.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "intClass.h"
|
||||||
|
#include "scriptError.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char* getStringValue(Variable_t* var) {
|
||||||
|
if (var->variableType != StringClass)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return var->string.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will NOT copy the string, the pointer is taken as-is
|
||||||
|
StringClass_t createStringClass(char* in, u8 free) {
|
||||||
|
StringClass_t a = { 0 };
|
||||||
|
a.free = free;
|
||||||
|
a.value = in;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t newStringVariable(char *x, u8 readOnly, u8 freeOnExit) {
|
||||||
|
Variable_t var = { .variableType = StringClass, .readOnly = readOnly, .string = createStringClass(x, freeOnExit) };
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(printStringVariable) {
|
||||||
|
if (caller->variableType == StringClass) {
|
||||||
|
StringClass_t* a = &caller->string;
|
||||||
|
gfx_printf("%s", a->value);
|
||||||
|
}
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(addStringVariables) {
|
||||||
|
char* s1 = getStringValue(caller);
|
||||||
|
char* s2 = getStringValue(*args);
|
||||||
|
|
||||||
|
char* n = malloc(strlen(s1) + strlen(s2) + 1);
|
||||||
|
strcpy(n, s1);
|
||||||
|
strcat(n, s2);
|
||||||
|
|
||||||
|
return newStringVariablePtr(n, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(getStringLength) {
|
||||||
|
char* s1 = getStringValue(caller);
|
||||||
|
return newIntVariablePtr(strlen(s1));
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(stringBytes) {
|
||||||
|
Variable_t v = { 0 };
|
||||||
|
v.variableType = ByteArrayClass;
|
||||||
|
u32 len = strlen(caller->string.value);
|
||||||
|
v.solvedArray.vector = newVec(1, len);
|
||||||
|
v.solvedArray.vector.count = len;
|
||||||
|
memcpy(v.solvedArray.vector.data, caller->string.value, len);
|
||||||
|
return copyVariableToPtr(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(stringIndexGet) {
|
||||||
|
u32 len = strlen(caller->string.value);
|
||||||
|
u32 idx = args[0]->integer.value;
|
||||||
|
if (len < idx || idx < 0) {
|
||||||
|
SCRIPT_FATAL_ERR("Index of string out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
char* a = calloc(1,2);
|
||||||
|
a[0] = caller->string.value[idx];
|
||||||
|
return newStringVariablePtr(a, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(stringMinusInt){
|
||||||
|
u32 baseStrLen = strlen(caller->string.value);
|
||||||
|
if (baseStrLen < args[0]->integer.value){
|
||||||
|
SCRIPT_FATAL_ERR("Index of string out of range");
|
||||||
|
}
|
||||||
|
char* newStr = calloc(baseStrLen - args[0]->integer.value + 1, 1);
|
||||||
|
memcpy(newStr, caller->string.value, baseStrLen - args[0]->integer.value);
|
||||||
|
return newStringVariablePtr(newStr, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(stringEq){
|
||||||
|
return newIntVariablePtr(!strcmp(caller->string.value, args[0]->string.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(stringInEq){
|
||||||
|
return newIntVariablePtr(strcmp(caller->string.value, args[0]->string.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(stringSplit) {
|
||||||
|
int valLen = strlen(args[0]->string.value);
|
||||||
|
|
||||||
|
char* start = caller->string.value;
|
||||||
|
char* find = NULL;
|
||||||
|
Vector_t arr = newVec(sizeof(char**), 1);
|
||||||
|
char* temp;
|
||||||
|
|
||||||
|
while ((find = (strstr(start, args[0]->string.value))) != NULL) {
|
||||||
|
temp = utils_copyStringSize(start, find - start);
|
||||||
|
vecAdd(&arr, temp);
|
||||||
|
|
||||||
|
start = find + valLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = utils_copyStringSize(start, caller->string.value + strlen(caller->string.value) - start);
|
||||||
|
vecAdd(&arr, temp);
|
||||||
|
|
||||||
|
Variable_t a = { .variableType = StringArrayClass, .solvedArray.vector = arr };
|
||||||
|
return copyVariableToPtr(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 strOneIntArg[] = { IntClass };
|
||||||
|
u8 oneStringArg[] = { StringClass };
|
||||||
|
|
||||||
|
ClassFunctionTableEntry_t stringFunctions[] = {
|
||||||
|
{"print", printStringVariable, 0, 0},
|
||||||
|
{"+", addStringVariables, 1, oneStringArg },
|
||||||
|
{"len", getStringLength, 0, 0},
|
||||||
|
{"bytes", stringBytes, 0, 0},
|
||||||
|
{"get", stringIndexGet, 1, strOneIntArg},
|
||||||
|
{"-", stringMinusInt, 1, strOneIntArg},
|
||||||
|
{"==", stringEq, 1, oneStringArg},
|
||||||
|
{"!=", stringInEq, 1, oneStringArg},
|
||||||
|
{"split", stringSplit, 1, oneStringArg},
|
||||||
|
{"/", stringSplit, 1, oneStringArg},
|
||||||
|
};
|
||||||
|
|
||||||
|
Variable_t getStringMember(Variable_t* var, char* memberName) {
|
||||||
|
return getGenericFunctionMember(var, memberName, stringFunctions, ARRAY_SIZE(stringFunctions));
|
||||||
|
}
|
||||||
10
source/script/StringClass.h
Normal file
10
source/script/StringClass.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "model.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
|
||||||
|
StringClass_t createStringClass(char* in, u8 free);
|
||||||
|
char* getStringValue(Variable_t* var);
|
||||||
|
|
||||||
|
Variable_t newStringVariable(char *x, u8 readOnly, u8 freeOnExit);
|
||||||
|
#define newStringVariablePtr(x, readOnly, freeOnExit) copyVariableToPtr(newStringVariable(x, readOnly, freeOnExit))
|
||||||
|
Variable_t getStringMember(Variable_t* var, char* memberName);
|
||||||
@@ -1,502 +0,0 @@
|
|||||||
#include "args.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include "functions.h"
|
|
||||||
#include "variables.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <mem/heap.h>
|
|
||||||
#include "../utils/utils.h"
|
|
||||||
|
|
||||||
char* utils_copyStringSize(const char* in, int size) {
|
|
||||||
if (size > strlen(in) || size < 0)
|
|
||||||
size = strlen(in);
|
|
||||||
|
|
||||||
char* out = calloc(size + 1, 1);
|
|
||||||
//strncpy(out, in, size);
|
|
||||||
if (size)
|
|
||||||
memcpy(out, in, size);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not include first openToken!
|
|
||||||
int distanceBetweenTokens(lexarToken_t* tokens, u32 len, int openToken, int closeToken) {
|
|
||||||
int i = 0;
|
|
||||||
int layer = 0;
|
|
||||||
for (; i < len; i++) {
|
|
||||||
if (tokens[i].token == openToken)
|
|
||||||
layer++;
|
|
||||||
else if (tokens[i].token == closeToken) {
|
|
||||||
if (layer == 0)
|
|
||||||
return i;
|
|
||||||
layer--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector_t extractVars(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len) {
|
|
||||||
Vector_t args = newVec(sizeof(Variable_t), 5);
|
|
||||||
int lastLoc = 0;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
if (tokens[i].token == LSBracket) {
|
|
||||||
int distance = distanceBetweenTokens(&tokens[i + 1], len - i - 1, LSBracket, RSBracket);
|
|
||||||
i += distance + 1;
|
|
||||||
}
|
|
||||||
if (tokens[i].token == LBracket){
|
|
||||||
int distance = distanceBetweenTokens(&tokens[i + 1], len - i - 1, LBracket, RBracket);
|
|
||||||
i += distance + 1;
|
|
||||||
}
|
|
||||||
if (tokens[i].token == Seperator) {
|
|
||||||
Variable_t res = solveEquation(ctx, &tokens[lastLoc], i - lastLoc, 0);
|
|
||||||
lastLoc = i + 1;
|
|
||||||
|
|
||||||
vecAddElement(&args, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i + 1 >= len) {
|
|
||||||
Variable_t res = solveEquation(ctx, &tokens[lastLoc], i + 1 - lastLoc, 0);
|
|
||||||
vecAddElement(&args, res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ErrValue(err) (Variable_t) {.varType = ErrType, .integerType = err}
|
|
||||||
#define IntValue(i) (Variable_t) {.varType = IntType, .integerType = i}
|
|
||||||
#define StrValue(s) (Variable_t) {.varType = StringType, .stringType = s}
|
|
||||||
|
|
||||||
#define ELIFTX(x) else if (tokens[i].token == x)
|
|
||||||
|
|
||||||
Variable_t getVarFromToken(scriptCtx_t* ctx, lexarToken_t* tokens, int* index, u32 maxLen) {
|
|
||||||
Variable_t val = { 0 };
|
|
||||||
int i = *index;
|
|
||||||
|
|
||||||
if (tokens[i].token == Variable) {
|
|
||||||
Variable_t* var = dictVectorFind(&ctx->varDict, tokens[i].text);
|
|
||||||
if (var != NULL) {
|
|
||||||
val = *var;
|
|
||||||
val.free = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val = ErrValue(ERRNOVAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ELIFTX(IntLit) {
|
|
||||||
val = IntValue(tokens[i].val);
|
|
||||||
}
|
|
||||||
ELIFTX(StrLit) {
|
|
||||||
val = StrValue(tokens[i].text);
|
|
||||||
val.free = 0;
|
|
||||||
}
|
|
||||||
ELIFTX(ArrayVariable) {
|
|
||||||
Variable_t* var = dictVectorFind(&ctx->varDict, tokens[i].text);
|
|
||||||
i += 2;
|
|
||||||
|
|
||||||
if (var == NULL)
|
|
||||||
return ErrValue(ERRNOVAR);
|
|
||||||
|
|
||||||
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LSBracket, RSBracket);
|
|
||||||
if (argCount < 0)
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
|
|
||||||
Variable_t index = solveEquation(ctx, &tokens[i], argCount, 0);
|
|
||||||
i += argCount;
|
|
||||||
|
|
||||||
if (index.varType != IntType)
|
|
||||||
return ErrValue(ERRINVALIDTYPE);
|
|
||||||
|
|
||||||
if (var->vectorType.count <= index.integerType || index.integerType < 0)
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
|
|
||||||
switch (var->varType) {
|
|
||||||
case StringArrayType:
|
|
||||||
val = StrValue((vecGetArray(char**, var->vectorType))[index.integerType]);
|
|
||||||
break;
|
|
||||||
case IntArrayType:
|
|
||||||
val = IntValue((vecGetArray(int*, var->vectorType))[index.integerType]);
|
|
||||||
break;
|
|
||||||
case ByteArrayType:
|
|
||||||
val = IntValue((vecGetArray(u8*, var->vectorType))[index.integerType]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ErrValue(ERRINVALIDTYPE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ELIFTX(Function) {
|
|
||||||
i += 2;
|
|
||||||
|
|
||||||
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LBracket, RBracket);
|
|
||||||
if (argCount < 0)
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
|
|
||||||
val = executeFunction(ctx, tokens[i - 2].text, &tokens[i], argCount);
|
|
||||||
|
|
||||||
i += argCount;
|
|
||||||
}
|
|
||||||
ELIFTX(LSBracket) {
|
|
||||||
i++;
|
|
||||||
|
|
||||||
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LSBracket, RSBracket);
|
|
||||||
if (argCount < 0)
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
|
|
||||||
val.varType = EmptyArrayType;
|
|
||||||
|
|
||||||
if (argCount > 0){
|
|
||||||
Vector_t arrayVars = extractVars(ctx, &tokens[i], argCount);
|
|
||||||
Variable_t* variables = vecGetArray(Variable_t*, arrayVars);
|
|
||||||
int type = variables[0].varType;
|
|
||||||
if (!(type == StringType || type == IntType))
|
|
||||||
return ErrValue(ERRINVALIDTYPE);
|
|
||||||
|
|
||||||
val.varType = (type + 2);
|
|
||||||
val.free = 1;
|
|
||||||
val.vectorType = newVec((type == IntType) ? sizeof(int) : sizeof(char*), arrayVars.count);
|
|
||||||
|
|
||||||
for (int j = 0; j < arrayVars.count; j++) {
|
|
||||||
if (variables[j].varType != type)
|
|
||||||
return ErrValue(ERRINVALIDTYPE); // Free-ing issue!!
|
|
||||||
|
|
||||||
if (type == StringType) {
|
|
||||||
char* temp = CpyStr(variables[j].stringType);
|
|
||||||
vecAddElement(&val.vectorType, temp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vecAddElement(&val.vectorType, variables[j].integerType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i += argCount;
|
|
||||||
freeVariableVector(&arrayVars);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ELIFTX(LBracket) {
|
|
||||||
i++;
|
|
||||||
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LBracket, RBracket);
|
|
||||||
if (argCount < 0)
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
|
|
||||||
val = solveEquation(ctx, &tokens[i], argCount, 0);
|
|
||||||
i += argCount;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// ERR
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
*index = i;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
int matchTypes(Variable_t d1, Variable_t d2, int type) {
|
|
||||||
return (d1.varType == d2.varType && d1.varType == type);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ELIFT(token) else if (localOpToken == token)
|
|
||||||
|
|
||||||
Variable_t solveEquation(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len, u8 shouldFree) {
|
|
||||||
Variable_t res = { 0 };
|
|
||||||
u8 lastToken = 0;
|
|
||||||
u8 invertValue = 0;
|
|
||||||
lexarToken_t* varToken = NULL;
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
if (tokens[i].token == Not)
|
|
||||||
invertValue = !invertValue;
|
|
||||||
|
|
||||||
else if (tokens[i].token == ArrayVariableAssignment || tokens[i].token == VariableAssignment) {
|
|
||||||
varToken = &tokens[i];
|
|
||||||
if (tokens[i].token == ArrayVariableAssignment) {
|
|
||||||
int distance = distanceBetweenTokens(&tokens[i] + 2, len, LSBracket, RSBracket);
|
|
||||||
i += distance + 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (tokens[i].token >= Variable && tokens[i].token <= LSBracket) {
|
|
||||||
Variable_t val = getVarFromToken(ctx, tokens, &i, len - i);
|
|
||||||
|
|
||||||
if (val.varType == ErrType)
|
|
||||||
return val;
|
|
||||||
|
|
||||||
if (val.varType == IntType && invertValue) {
|
|
||||||
val.integerType = !val.integerType;
|
|
||||||
}
|
|
||||||
invertValue = 0;
|
|
||||||
|
|
||||||
if (lastToken) {
|
|
||||||
u16 localOpToken = lastToken; // do we need local op token?
|
|
||||||
lastToken = 0;
|
|
||||||
|
|
||||||
if (matchTypes(res, val, IntType)) {
|
|
||||||
if (localOpToken == Plus)
|
|
||||||
res.integerType += val.integerType;
|
|
||||||
ELIFT(Minus)
|
|
||||||
res.integerType -= val.integerType;
|
|
||||||
ELIFT(Multiply)
|
|
||||||
res.integerType *= val.integerType;
|
|
||||||
ELIFT(Division) {
|
|
||||||
if (!val.integerType)
|
|
||||||
res = ErrValue(ERRDIVBYZERO);
|
|
||||||
else
|
|
||||||
res.integerType = res.integerType / val.integerType;
|
|
||||||
}
|
|
||||||
ELIFT(Mod)
|
|
||||||
res.integerType %= val.integerType;
|
|
||||||
ELIFT(Smaller)
|
|
||||||
res.integerType = res.integerType < val.integerType;
|
|
||||||
ELIFT(SmallerEqual)
|
|
||||||
res.integerType = res.integerType <= val.integerType;
|
|
||||||
ELIFT(Bigger)
|
|
||||||
res.integerType = res.integerType > val.integerType;
|
|
||||||
ELIFT(BiggerEqual)
|
|
||||||
res.integerType = res.integerType >= val.integerType;
|
|
||||||
ELIFT(EqualEqual)
|
|
||||||
res.integerType = res.integerType == val.integerType;
|
|
||||||
ELIFT(NotEqual)
|
|
||||||
res.integerType = res.integerType != val.integerType;
|
|
||||||
ELIFT(LogicAND) {
|
|
||||||
res.integerType = res.integerType && val.integerType;
|
|
||||||
if (!res.integerType)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ELIFT(LogicOR) {
|
|
||||||
res.integerType = res.integerType || val.integerType;
|
|
||||||
if (res.integerType)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ELIFT(AND)
|
|
||||||
res.integerType = res.integerType & val.integerType;
|
|
||||||
ELIFT(OR)
|
|
||||||
res.integerType = res.integerType | val.integerType;
|
|
||||||
ELIFT(BitShiftLeft)
|
|
||||||
res.integerType = res.integerType << val.integerType;
|
|
||||||
ELIFT(BitShiftRight)
|
|
||||||
res.integerType = res.integerType >> val.integerType;
|
|
||||||
else
|
|
||||||
return ErrValue(ERRBADOPERATOR);
|
|
||||||
}
|
|
||||||
else if (matchTypes(res, val, StringType)) {
|
|
||||||
if (localOpToken == Plus) {
|
|
||||||
char* buff = calloc(strlen(res.stringType) + strlen(val.stringType) + 1, 1);
|
|
||||||
strcpy(buff, res.stringType);
|
|
||||||
strcat(buff, val.stringType);
|
|
||||||
|
|
||||||
if (res.free) free(res.stringType); // we should replace these with variablefree
|
|
||||||
if (val.free) free(val.stringType);
|
|
||||||
res.stringType = buff;
|
|
||||||
res.free = 1;
|
|
||||||
}
|
|
||||||
ELIFT(EqualEqual) {
|
|
||||||
res.typeUnion = IntType;
|
|
||||||
int compRes = !strcmp(res.stringType, val.stringType);
|
|
||||||
if (res.free) free(res.stringType);
|
|
||||||
if (val.free) free(val.stringType);
|
|
||||||
res.integerType = compRes;
|
|
||||||
res.free = 0;
|
|
||||||
}
|
|
||||||
ELIFT(Minus) {
|
|
||||||
u32 lenRes = strlen(res.stringType);
|
|
||||||
u32 valRes = strlen(val.stringType);
|
|
||||||
if (!strcmp(res.stringType + lenRes - valRes, val.stringType)) {
|
|
||||||
char *temp = malloc(lenRes - valRes + 1);
|
|
||||||
memcpy(temp, res.stringType, lenRes - valRes);
|
|
||||||
temp[lenRes - valRes] = 0;
|
|
||||||
freeVariable(res);
|
|
||||||
res.free = 1;
|
|
||||||
res.stringType = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
freeVariable(val);
|
|
||||||
}
|
|
||||||
ELIFT(Division) {
|
|
||||||
int valLen = strlen(val.stringType);
|
|
||||||
if (!valLen) {
|
|
||||||
res = ErrValue(ERRSYNTAX);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* start = res.stringType;
|
|
||||||
char* find = NULL;
|
|
||||||
Vector_t arr = newVec(sizeof(char**), 10);
|
|
||||||
char* temp;
|
|
||||||
|
|
||||||
while ((find = (strstr(start, val.stringType))) != NULL) {
|
|
||||||
temp = utils_copyStringSize(start, find - start);
|
|
||||||
vecAddElement(&arr, temp);
|
|
||||||
|
|
||||||
start = find + valLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = utils_copyStringSize(start, res.stringType + strlen(res.stringType) - start);
|
|
||||||
vecAddElement(&arr, temp);
|
|
||||||
if (res.free) free(res.stringType); // do we free here?
|
|
||||||
if (val.free) free(val.stringType);
|
|
||||||
|
|
||||||
res.varType = StringArrayType;
|
|
||||||
res.free = 1;
|
|
||||||
res.vectorType = arr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return ErrValue(ERRBADOPERATOR);
|
|
||||||
}
|
|
||||||
else if ((res.varType == IntArrayType || res.varType == ByteArrayType) && val.varType == IntType) {
|
|
||||||
if (localOpToken == Plus) {
|
|
||||||
Vector_t newV = vecCopy(&res.vectorType);
|
|
||||||
freeVariable(res);
|
|
||||||
res.vectorType = newV;
|
|
||||||
res.free = 1;
|
|
||||||
if (res.varType == IntArrayType)
|
|
||||||
vecAddElement(&res.vectorType, val.integerType);
|
|
||||||
else {
|
|
||||||
u8 in = ((u8)val.integerType & 0xFF);
|
|
||||||
vecAddElement(&res.vectorType, in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ELIFT(Minus){
|
|
||||||
if (val.integerType >= res.vectorType.count)
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
|
|
||||||
res.vectorType.count -= val.integerType;
|
|
||||||
Vector_t newV = vecCopy(&res.vectorType);
|
|
||||||
freeVariable(res);
|
|
||||||
res.vectorType = newV;
|
|
||||||
res.free = 1;
|
|
||||||
}
|
|
||||||
ELIFT(Selector){
|
|
||||||
if (val.integerType >= res.vectorType.count)
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
|
|
||||||
Vector_t newV = vecCopyOffset(&res.vectorType, val.integerType);
|
|
||||||
freeVariable(res);
|
|
||||||
res.vectorType = newV;
|
|
||||||
res.free = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (res.varType == StringType && val.varType == IntType){
|
|
||||||
if (localOpToken == Minus){
|
|
||||||
u32 resLen = strlen(res.stringType);
|
|
||||||
if (resLen < val.integerType)
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
|
|
||||||
char *temp = utils_copyStringSize(res.stringType, resLen - val.integerType);
|
|
||||||
|
|
||||||
freeVariable(res);
|
|
||||||
res.stringType = temp;
|
|
||||||
res.free = 1;
|
|
||||||
}
|
|
||||||
ELIFT(Selector){
|
|
||||||
u32 resLen = strlen(res.stringType);
|
|
||||||
if (resLen < val.integerType)
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
|
|
||||||
char *temp = CpyStr(res.stringType + val.integerType);
|
|
||||||
|
|
||||||
freeVariable(res);
|
|
||||||
res.stringType = temp;
|
|
||||||
res.free = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return ErrValue(ERRBADOPERATOR);
|
|
||||||
}
|
|
||||||
else if (res.varType == EmptyArrayType && localOpToken == Plus){
|
|
||||||
res.free = 1;
|
|
||||||
res.varType = val.varType + 2;
|
|
||||||
|
|
||||||
if (val.varType == IntType){
|
|
||||||
res.vectorType = newVec(sizeof(int), 4);
|
|
||||||
vecAddElem(&res.vectorType, val.integerType);
|
|
||||||
}
|
|
||||||
else if (val.varType == StringType) {
|
|
||||||
res.vectorType = newVec(sizeof(char*), 4);
|
|
||||||
char *temp = CpyStr(val.stringType);
|
|
||||||
vecAddElem(&res.vectorType, temp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return ErrValue(ERRBADOPERATOR);
|
|
||||||
|
|
||||||
freeVariable(val);
|
|
||||||
}
|
|
||||||
else if (res.varType == StringArrayType && val.varType == StringType){
|
|
||||||
if (localOpToken == Plus){
|
|
||||||
Vector_t new = vecCopy(&res.vectorType);
|
|
||||||
vecDefArray(char **, strings, new);
|
|
||||||
for (int j = 0; j < new.count; j++){
|
|
||||||
strings[j] = CpyStr(strings[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
freeVariable(res);
|
|
||||||
|
|
||||||
char *temp = CpyStr(val.stringType);
|
|
||||||
vecAddElem(&new, temp);
|
|
||||||
|
|
||||||
res.free = 1;
|
|
||||||
res.vectorType = new;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return ErrValue(ERRBADOPERATOR);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return ErrValue(ERRBADOPERATOR);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (tokens[i].token >= Plus && tokens[i].token <= BitShiftRight) {
|
|
||||||
lastToken = tokens[i].token;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (varToken != NULL) {
|
|
||||||
if (varToken->token == VariableAssignment) {
|
|
||||||
dict_t newVar = newDict(CpyStr(varToken->text), res);
|
|
||||||
dictVectorAdd(&ctx->varDict, newVar);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Variable_t* var = dictVectorFind(&ctx->varDict, varToken->text);
|
|
||||||
if (var != NULL) {
|
|
||||||
if (var->varType - 2 == res.varType || (var->varType == ByteArrayType && res.varType == IntType)) {
|
|
||||||
int distance = distanceBetweenTokens(varToken + 2, len, LSBracket, RSBracket);
|
|
||||||
if (distance < 0) {
|
|
||||||
// ERR
|
|
||||||
return ErrValue(ERRSYNTAX);
|
|
||||||
}
|
|
||||||
Variable_t index = solveEquation(ctx, varToken + 2, distance, 0);
|
|
||||||
if (index.varType != IntType) {
|
|
||||||
// ERR
|
|
||||||
}
|
|
||||||
else if (index.integerType < 0 || var->vectorType.count <= index.integerType) {
|
|
||||||
// ERR
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (var->varType == IntArrayType) {
|
|
||||||
int* arr = vecGetArray(int*, var->vectorType);
|
|
||||||
arr[index.integerType] = res.integerType;
|
|
||||||
}
|
|
||||||
else if (var->varType == StringArrayType) {
|
|
||||||
char** arr = vecGetArray(char**, var->vectorType);
|
|
||||||
arr[index.integerType] = CpyStr(res.stringType);
|
|
||||||
}
|
|
||||||
else if (var->varType == ByteArrayType) {
|
|
||||||
u8* arr = vecGetArray(u8*, var->vectorType);
|
|
||||||
arr[index.integerType] = res.integerType & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// ERR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//ERR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (shouldFree) // we should get rid of this ugly free. why not set .free to 0 when assigning it then free in parser.c?
|
|
||||||
freeVariable(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
char* utils_copyStringSize(const char* in, int size);
|
|
||||||
Variable_t solveEquation(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len, u8 shouldFree);
|
|
||||||
int distanceBetweenTokens(lexarToken_t* tokens, u32 len, int openToken, int closeToken);
|
|
||||||
Vector_t extractVars(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len);
|
|
||||||
272
source/script/arrayClass.c
Normal file
272
source/script/arrayClass.c
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
#include "model.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
#include "intClass.h"
|
||||||
|
#include "arrayClass.h"
|
||||||
|
#include "garbageCollector.h"
|
||||||
|
#include "eval.h"
|
||||||
|
#include "scriptError.h"
|
||||||
|
#include "StringClass.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
u8 anotherOneIntArg[] = { IntClass };
|
||||||
|
u8 oneStringoneFunction[] = { StringClass, FunctionClass };
|
||||||
|
u8 doubleInt[] = {IntClass, IntClass};
|
||||||
|
u8 oneIntOneAny[] = { IntClass, VARARGCOUNT };
|
||||||
|
u8 anotherAnotherOneVarArg[] = { VARARGCOUNT };
|
||||||
|
u8 oneByteArrayClass[] = {ByteArrayClass};
|
||||||
|
u8 oneIntArrayClass[] = {IntArrayClass};
|
||||||
|
|
||||||
|
Variable_t arrayClassGetIdx(Variable_t *caller, s64 idx) {
|
||||||
|
if (caller->variableType == IntArrayClass) {
|
||||||
|
s64* arr = caller->solvedArray.vector.data;
|
||||||
|
return newIntVariable(arr[idx]);
|
||||||
|
}
|
||||||
|
else if (caller->variableType == StringArrayClass) {
|
||||||
|
char** arr = caller->solvedArray.vector.data;
|
||||||
|
Variable_t v = newStringVariable(arr[idx], 1, 0);
|
||||||
|
v.readOnly = 1;
|
||||||
|
v.reference = 1;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
else if (caller->variableType == ByteArrayClass) {
|
||||||
|
u8* arr = caller->solvedArray.vector.data;
|
||||||
|
return newIntVariable(arr[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Variable_t) { 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
int arrayClassAdd(Variable_t *caller, Variable_t *add){
|
||||||
|
if (caller->variableType == IntArrayClass) {
|
||||||
|
if (add->variableType != IntClass) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vecAdd(&caller->solvedArray.vector, add->integer.value);
|
||||||
|
}
|
||||||
|
else if (caller->variableType == StringArrayClass) {
|
||||||
|
if (add->variableType != StringClass) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* str = CpyStr(add->string.value);
|
||||||
|
vecAdd(&caller->solvedArray.vector, str);
|
||||||
|
}
|
||||||
|
else if (caller->variableType == ByteArrayClass) {
|
||||||
|
if (add->variableType != IntClass) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 val = (u8)(add->integer.value & 0xFF);
|
||||||
|
vecAdd(&caller->solvedArray.vector, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(getArrayIdx) {
|
||||||
|
s64 getVal = (*args)->integer.value;
|
||||||
|
// Out of bounds
|
||||||
|
if (getVal < 0 || getVal >= caller->solvedArray.vector.count) {
|
||||||
|
SCRIPT_FATAL_ERR("Accessing index %d while array is %d long", (int)getVal, (int)caller->solvedArray.vector.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t a = arrayClassGetIdx(caller, getVal);
|
||||||
|
if (a.variableType == None)
|
||||||
|
return NULL;
|
||||||
|
return copyVariableToPtr(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(getArrayLen) {
|
||||||
|
return newIntVariablePtr(caller->solvedArray.vector.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(arraySlice) {
|
||||||
|
s64 skipAmount = getIntValue(*args);
|
||||||
|
s64 takeAmount = getIntValue(args[1]);
|
||||||
|
|
||||||
|
if (caller->solvedArray.vector.count < (skipAmount + takeAmount) || skipAmount < 0 || takeAmount <= 0) {
|
||||||
|
SCRIPT_FATAL_ERR("Slicing out of range of array with len %d", (int)caller->solvedArray.vector.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t refSkip = { .variableType = SolvedArrayReferenceClass };
|
||||||
|
refSkip.solvedArray.arrayClassReference = caller;
|
||||||
|
refSkip.solvedArray.offset = skipAmount;
|
||||||
|
refSkip.solvedArray.len = takeAmount;
|
||||||
|
addPendingReference(caller);
|
||||||
|
return copyVariableToPtr(refSkip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: arrayForEach does not like the new garbage collector
|
||||||
|
ClassFunction(arrayForEach) {
|
||||||
|
Vector_t* v = &caller->solvedArray.vector;
|
||||||
|
|
||||||
|
Callback_SetVar_t setVar = { .isTopLevel = 1, .varName = (*args)->string.value };
|
||||||
|
Variable_t* iter = NULL;
|
||||||
|
iter = copyVariableToPtr(newIntVariable(0));
|
||||||
|
iter->gcDoNotFree = 1;
|
||||||
|
runtimeVariableEdit(&setVar, iter);
|
||||||
|
|
||||||
|
for (int i = 0; i < v->count; i++) {
|
||||||
|
*iter = arrayClassGetIdx(caller, i);
|
||||||
|
iter->gcDoNotFree = 1;
|
||||||
|
|
||||||
|
Variable_t* res = genericCallDirect(args[1], NULL, 0);
|
||||||
|
if (res == NULL) {
|
||||||
|
if (scriptLastError == SCRIPT_BREAK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iter->reference = 1;
|
||||||
|
free(iter);
|
||||||
|
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(arrayCopy) {
|
||||||
|
Vector_t* v = &caller->solvedArray.vector;
|
||||||
|
Vector_t copiedArray = vecCopy(v);
|
||||||
|
Variable_t var = { .variableType = caller->variableType, .solvedArray.vector = copiedArray };
|
||||||
|
return copyVariableToPtr(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(arraySet) {
|
||||||
|
s64 idx = getIntValue(*args);
|
||||||
|
Vector_t* v = &caller->solvedArray.vector;
|
||||||
|
if (v->count < idx || idx < 0) {
|
||||||
|
SCRIPT_FATAL_ERR("Accessing index %d while array is %d long", (int)idx, (int)caller->solvedArray.vector.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 oldCount = caller->solvedArray.vector.count;
|
||||||
|
caller->solvedArray.vector.count = idx;
|
||||||
|
if (arrayClassAdd(caller, args[1])){
|
||||||
|
SCRIPT_FATAL_ERR("Adding the wrong type to a typed array");
|
||||||
|
}
|
||||||
|
caller->solvedArray.vector.count = oldCount;
|
||||||
|
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(arrayAdd) {
|
||||||
|
Variable_t* arg = *args;
|
||||||
|
|
||||||
|
if (caller->readOnly) {
|
||||||
|
SCRIPT_FATAL_ERR("Array is read-only");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrayClassAdd(caller, arg)){
|
||||||
|
SCRIPT_FATAL_ERR("Adding the wrong type to a typed array");
|
||||||
|
}
|
||||||
|
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(arrayContains) {
|
||||||
|
Vector_t* v = &caller->solvedArray.vector;
|
||||||
|
Variable_t* arg = *args;
|
||||||
|
|
||||||
|
for (int i = 0; i < v->count; i++) {
|
||||||
|
Variable_t iter = arrayClassGetIdx(caller, i);
|
||||||
|
|
||||||
|
if (iter.variableType != arg->variableType){
|
||||||
|
SCRIPT_FATAL_ERR("type of contains does not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caller->variableType == StringArrayClass) {
|
||||||
|
if (!strcmp(arg->string.value, iter.string.value))
|
||||||
|
return newIntVariablePtr(i + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (arg->integer.value == iter.integer.value)
|
||||||
|
return newIntVariablePtr(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newIntVariablePtr(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(arrayMinus) {
|
||||||
|
s64 count = getIntValue(*args);
|
||||||
|
Vector_t* v = &caller->solvedArray.vector;
|
||||||
|
if (v->count < count || count <= 0) {
|
||||||
|
SCRIPT_FATAL_ERR("Accessing index %d while array is %d long", (int)count, (int)caller->solvedArray.vector.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caller->variableType == StringArrayClass) {
|
||||||
|
char** arr = v->data;
|
||||||
|
for (int i = v->count - count; i < count; i++) {
|
||||||
|
FREE(arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v->count -= count;
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(bytesToStr) {
|
||||||
|
if (caller->variableType != ByteArrayClass) {
|
||||||
|
SCRIPT_FATAL_ERR("Need a bytearray to convert to str");
|
||||||
|
}
|
||||||
|
|
||||||
|
char* buff = malloc(caller->solvedArray.vector.count + 1);
|
||||||
|
memcpy(buff, caller->solvedArray.vector.data, caller->solvedArray.vector.count);
|
||||||
|
buff[caller->solvedArray.vector.count] = '\0';
|
||||||
|
return newStringVariablePtr(buff, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(eqArray){
|
||||||
|
Variable_t *arg = (*args);
|
||||||
|
if (caller->solvedArray.vector.count != arg->solvedArray.vector.count || arg->variableType != caller->variableType){
|
||||||
|
return newIntVariablePtr(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 res = memcmp(caller->solvedArray.vector.data, arg->solvedArray.vector.data, caller->solvedArray.vector.count * caller->solvedArray.vector.elemSz);
|
||||||
|
return newIntVariablePtr(!res);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(arrayFind){
|
||||||
|
Variable_t *arg = (*args);
|
||||||
|
if (caller->solvedArray.vector.count <= arg->solvedArray.vector.count || arg->variableType != caller->variableType){
|
||||||
|
return newIntVariablePtr(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 step = (arg->variableType == ByteArrayClass) ? 1 : 8;
|
||||||
|
char *haystack = caller->solvedArray.vector.data;
|
||||||
|
void *needle = arg->solvedArray.vector.data;
|
||||||
|
|
||||||
|
for (int i = 0; i < caller->solvedArray.vector.count - arg->solvedArray.vector.count; i++){
|
||||||
|
if (!memcmp(haystack + (i * step), needle, step * arg->solvedArray.vector.count)){
|
||||||
|
return newIntVariablePtr(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newIntVariablePtr(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunctionTableEntry_t arrayFunctions[] = {
|
||||||
|
{"get", getArrayIdx, 1, anotherOneIntArg },
|
||||||
|
{"len", getArrayLen, 0, 0},
|
||||||
|
{"slice", arraySlice, 2, doubleInt},
|
||||||
|
{"foreach", arrayForEach, 2, oneStringoneFunction},
|
||||||
|
{"copy", arrayCopy, 0, 0},
|
||||||
|
{"set", arraySet, 2, oneIntOneAny},
|
||||||
|
{"+", arrayAdd, 1, anotherAnotherOneVarArg},
|
||||||
|
{"add", arrayAdd, 1, anotherAnotherOneVarArg},
|
||||||
|
{"-", arrayMinus, 1, anotherOneIntArg},
|
||||||
|
{"contains", arrayContains, 1, anotherAnotherOneVarArg},
|
||||||
|
{"bytestostr", bytesToStr, 0, 0},
|
||||||
|
{"==", eqArray, 1, oneByteArrayClass},
|
||||||
|
{"==", eqArray, 1, oneIntArrayClass},
|
||||||
|
{"find", arrayFind, 1, oneByteArrayClass},
|
||||||
|
{"find", arrayFind, 1, oneIntArrayClass},
|
||||||
|
};
|
||||||
|
|
||||||
|
Variable_t getArrayMember(Variable_t* var, char* memberName) {
|
||||||
|
return getGenericFunctionMember(var, memberName, arrayFunctions, ARRAY_SIZE(arrayFunctions));
|
||||||
|
}
|
||||||
5
source/script/arrayClass.h
Normal file
5
source/script/arrayClass.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "model.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
|
||||||
|
Variable_t getArrayMember(Variable_t* var, char* memberName);
|
||||||
24
source/script/arrayReferenceClass.c
Normal file
24
source/script/arrayReferenceClass.c
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include "model.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
#include "intClass.h"
|
||||||
|
#include "arrayReferenceClass.h"
|
||||||
|
|
||||||
|
|
||||||
|
ClassFunction(projectArray) {
|
||||||
|
Variable_t newArray = { .variableType = caller->solvedArray.arrayClassReference->variableType, .reference = 1, .readOnly = 1 };
|
||||||
|
|
||||||
|
newArray.solvedArray.vector = caller->solvedArray.arrayClassReference->solvedArray.vector;
|
||||||
|
newArray.solvedArray.vector.data = (u8*)caller->solvedArray.arrayClassReference->solvedArray.vector.data + (caller->solvedArray.offset * caller->solvedArray.arrayClassReference->solvedArray.vector.elemSz);
|
||||||
|
newArray.solvedArray.vector.count = caller->solvedArray.len;
|
||||||
|
|
||||||
|
return copyVariableToPtr(newArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunctionTableEntry_t arrayReferenceFunctions[] = {
|
||||||
|
{"project", projectArray, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
Variable_t getArrayReferenceMember(Variable_t* var, char* memberName) {
|
||||||
|
return getGenericFunctionMember(var, memberName, arrayReferenceFunctions, ARRAY_SIZE(arrayReferenceFunctions));
|
||||||
|
}
|
||||||
5
source/script/arrayReferenceClass.h
Normal file
5
source/script/arrayReferenceClass.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "model.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
|
||||||
|
Variable_t getArrayReferenceMember(Variable_t* var, char* memberName);
|
||||||
23
source/script/compat.h
Normal file
23
source/script/compat.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#define gfx_printf(str, ...) printf(str, ##__VA_ARGS__)
|
||||||
|
#define gfx_vprintf(str, va) vprintf(str, va);
|
||||||
|
#define gfx_putc(x) gfx_printf("%c", x)
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||||
|
#define LP_VER_MJ 3
|
||||||
|
#define LP_VER_MN 0
|
||||||
|
#define LP_VER_BF 5
|
||||||
|
#define LP_VER "3.0.5"
|
||||||
|
#define FREE(x) if (x) free(x)
|
||||||
|
#define CpyStr(x) _strdup(x)
|
||||||
|
#include "vector.h"
|
||||||
|
#pragma _CRT_SECURE_NO_WARNINGS
|
||||||
|
#else
|
||||||
|
#include "../gfx/gfx.h"
|
||||||
|
#include <mem/heap.h>
|
||||||
|
#include "../utils/vector.h"
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#endif
|
||||||
61
source/script/dictionaryClass.c
Normal file
61
source/script/dictionaryClass.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#include "dictionaryClass.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "garbageCollector.h"
|
||||||
|
#include "intClass.h"
|
||||||
|
|
||||||
|
u8 dictOneStrOneAll[] = { StringClass, VARARGCOUNT };
|
||||||
|
|
||||||
|
void addVariableToDict(Variable_t *dict, char* name, Variable_t *add){
|
||||||
|
Dict_t a = {.name = CpyStr(name), .var = add};
|
||||||
|
vecAdd(&dict->dictionary.vector, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addIntToDict(Variable_t *dict, char* name, s64 integer){
|
||||||
|
Variable_t *v = newIntVariablePtr(integer);
|
||||||
|
addVariableToDict(dict, name, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dict_t* getEntry(Vector_t *v, char* name) {
|
||||||
|
vecForEach(Dict_t*, dict, v) {
|
||||||
|
if (!strcmp(name, dict->name)) {
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(dictSet) {
|
||||||
|
addPendingReference(args[1]);
|
||||||
|
char* arg = CpyStr(args[0]->string.value);
|
||||||
|
Dict_t* possibleEntry = getEntry(&caller->dictionary.vector, arg);
|
||||||
|
if (possibleEntry == NULL) {
|
||||||
|
Dict_t a = { .name = arg, .var = args[1] };
|
||||||
|
vecAdd(&caller->dictionary.vector, a);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
possibleEntry->var = args[1];
|
||||||
|
free(arg);
|
||||||
|
}
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunctionTableEntry_t dictFunctions[] = {
|
||||||
|
{"set", dictSet, 2, dictOneStrOneAll},
|
||||||
|
};
|
||||||
|
|
||||||
|
Variable_t getDictMember(Variable_t* var, char* memberName) {
|
||||||
|
if (!strcmp(memberName, "set"))
|
||||||
|
return getGenericFunctionMember(var, memberName, dictFunctions, ARRAY_SIZE(dictFunctions));
|
||||||
|
|
||||||
|
vecForEach(Dict_t*, dict, (&var->dictionary.vector)) {
|
||||||
|
if (!strcmp(dict->name, memberName)) {
|
||||||
|
Variable_t a = { 0 };
|
||||||
|
a.variableType = ReferenceType;
|
||||||
|
a.referenceType = dict->var;
|
||||||
|
addPendingReference(dict->var);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Variable_t) { 0 };
|
||||||
|
}
|
||||||
8
source/script/dictionaryClass.h
Normal file
8
source/script/dictionaryClass.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "model.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
Variable_t getDictMember(Variable_t* var, char* memberName);
|
||||||
|
void addVariableToDict(Variable_t *dict, char* name, Variable_t *add);
|
||||||
|
void addIntToDict(Variable_t *dict, char* name, s64 integer);
|
||||||
22
source/script/else.c
Normal file
22
source/script/else.c
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "else.h"
|
||||||
|
|
||||||
|
ClassFunction(scriptElse) {
|
||||||
|
if (!caller->integer.value) {
|
||||||
|
Variable_t* res = genericCallDirect(args[0], NULL, 0);
|
||||||
|
if (res == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
removePendingReference(res);
|
||||||
|
}
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 elseOneFunction[] = { FunctionClass };
|
||||||
|
|
||||||
|
ClassFunctionTableEntry_t elseFunctions[] = {
|
||||||
|
{"else", scriptElse, 1, elseOneFunction},
|
||||||
|
};
|
||||||
|
|
||||||
|
Variable_t getElseMember(Variable_t* var, char* memberName) {
|
||||||
|
return getGenericFunctionMember(var, memberName, elseFunctions, ARRAY_SIZE(elseFunctions));
|
||||||
|
}
|
||||||
7
source/script/else.h
Normal file
7
source/script/else.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "model.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "garbageCollector.h"
|
||||||
|
|
||||||
|
Variable_t getElseMember(Variable_t* var, char* memberName);
|
||||||
276
source/script/eval.c
Normal file
276
source/script/eval.c
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
#include "model.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
#include "eval.h"
|
||||||
|
#include "garbageCollector.h"
|
||||||
|
#include "standardLibrary.h"
|
||||||
|
#include "scriptError.h"
|
||||||
|
#include "StringClass.h"
|
||||||
|
#include "intClass.h"
|
||||||
|
#include "unsolvedArrayClass.h"
|
||||||
|
#include "functionClass.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
Variable_t* staticVars;
|
||||||
|
|
||||||
|
void setStaticVars(Vector_t* vec) {
|
||||||
|
staticVars = vec->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector_t runtimeVars;
|
||||||
|
|
||||||
|
void initRuntimeVars() {
|
||||||
|
runtimeVars = newVec(sizeof(Dict_t), 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void exitRuntimeVars() {
|
||||||
|
vecForEach(Dict_t*, runtimeVar, (&runtimeVars)) {
|
||||||
|
FREE(runtimeVar->name);
|
||||||
|
removePendingReference(runtimeVar->var);
|
||||||
|
}
|
||||||
|
|
||||||
|
vecFree(runtimeVars);
|
||||||
|
runtimeVars.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* opToVar(Operator_t* op, Callback_SetVar_t *setCallback, u8 possibleCallArg) {
|
||||||
|
Variable_t* var = NULL;
|
||||||
|
CallArgs_t* args = NULL;
|
||||||
|
|
||||||
|
if ((op + 1)->token == CallArgs && possibleCallArg)
|
||||||
|
args = &(op + 1)->callArgs;
|
||||||
|
|
||||||
|
if (op->token == BetweenBrackets) {
|
||||||
|
var = eval(op->variable.betweenBrackets.data, op->variable.betweenBrackets.len, 1);
|
||||||
|
}
|
||||||
|
else if (op->token == Variable) {
|
||||||
|
if (op->variable.staticVariableSet) {
|
||||||
|
if (op->variable.staticVariableRef) {
|
||||||
|
op->variable.staticVariable = &staticVars[(int)op->variable.staticVariable];
|
||||||
|
op->variable.staticVariableRef = 0;
|
||||||
|
op->variable.staticVariable->readOnly = 1;
|
||||||
|
op->variable.staticVariable->reference = 1;
|
||||||
|
op->variable.staticVariable->gcDoNotFree = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var = op->variable.staticVariable;
|
||||||
|
|
||||||
|
if (var->variableType == UnresolvedArrayClass) {
|
||||||
|
var = solveArray(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (op->variable.staticVariableType > 0) {
|
||||||
|
if (op->variable.staticVariableType == 1) {
|
||||||
|
var = copyVariableToPtr(newIntVariable(op->variable.integerType));
|
||||||
|
}
|
||||||
|
else if (op->variable.staticVariableType == 2) {
|
||||||
|
var = copyVariableToPtr(newStringVariable(op->variable.stringType, 1, 0));
|
||||||
|
var->reference = 1;
|
||||||
|
}
|
||||||
|
else if (op->variable.staticVariableType == 3) {
|
||||||
|
var = copyVariableToPtr(newFunctionVariable(createFunctionClass((Function_t) { 0 }, op->variable.staticFunction)));
|
||||||
|
var->function.len = op->variable.staticFunctionLen;
|
||||||
|
var->reference = 1;
|
||||||
|
|
||||||
|
|
||||||
|
if (!strcmp(var->function.builtInPtr->name,"while")) {
|
||||||
|
var->function.firstArgAsFunction = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (args != NULL) {
|
||||||
|
if (args->action == ActionSet && args->extraAction == ActionExtraNone) {
|
||||||
|
setCallback->isTopLevel = 1;
|
||||||
|
setCallback->varName = op->variable.name;
|
||||||
|
setCallback->hasVarName = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vecForEach(Dict_t*, variableArrayEntry, (&runtimeVars)) {
|
||||||
|
if (!strcmp(variableArrayEntry->name, op->variable.name)) {
|
||||||
|
var = variableArrayEntry->var;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var == NULL) {
|
||||||
|
SCRIPT_FATAL_ERR("Variable '%s' not found", op->variable.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
addPendingReference(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (args) {
|
||||||
|
Variable_t* varNext = NULL;
|
||||||
|
if (args->action == ActionGet) {
|
||||||
|
if (args->extraAction == ActionExtraMemberName && args->next != NULL && args->next->action == ActionCall) {
|
||||||
|
varNext = callMemberFunction(var, args->extra, args->next);
|
||||||
|
args = args->next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
varNext = genericGet(var, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (args->action == ActionSet) {
|
||||||
|
if (var->readOnly) {
|
||||||
|
SCRIPT_FATAL_ERR("Variable which set was called on is read-only");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args->extraAction == ActionExtraMemberName || args->extraAction == ActionExtraArrayIndex) {
|
||||||
|
setCallback->hasVarName = (args->extraAction == ActionExtraMemberName) ? 1 : 0;
|
||||||
|
setCallback->setVar = var;
|
||||||
|
if (args->extraAction == ActionExtraMemberName) {
|
||||||
|
setCallback->varName = args->extra;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setCallback->idxVar = args->extra;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCRIPT_FATAL_ERR("Unexpected set!");
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (args->action == ActionCall) {
|
||||||
|
varNext = genericCall(var, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (varNext == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
removePendingReference(var);
|
||||||
|
|
||||||
|
//if (!var->reference)
|
||||||
|
// freeVariable(&var);
|
||||||
|
|
||||||
|
var = varNext;
|
||||||
|
args = args->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op->not && var) {
|
||||||
|
Variable_t* newVar = callMemberFunctionDirect(var, "not", NULL, 0);
|
||||||
|
removePendingReference(var);
|
||||||
|
var = newVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
void runtimeVariableEdit(Callback_SetVar_t* set, Variable_t* curRes) {
|
||||||
|
if (set->isTopLevel) {
|
||||||
|
vecForEach(Dict_t*, variableArrayEntry, (&runtimeVars)) {
|
||||||
|
if (!strcmp(variableArrayEntry->name, set->varName)) {
|
||||||
|
removePendingReference(variableArrayEntry->var);
|
||||||
|
//addPendingReference(curRes);
|
||||||
|
variableArrayEntry->var = curRes;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dict_t newStoredVariable = { 0 };
|
||||||
|
newStoredVariable.name = CpyStr(set->varName);
|
||||||
|
newStoredVariable.var = curRes;
|
||||||
|
vecAdd(&runtimeVars, newStoredVariable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set->idxVar) {
|
||||||
|
Variable_t* var = eval(set->idxVar->operations.data, set->idxVar->operations.count, 1);
|
||||||
|
Variable_t* args[2] = { var, curRes };
|
||||||
|
callMemberFunctionDirect(set->setVar, "set", args, 2);
|
||||||
|
removePendingReference(var);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Variable_t varName = { .variableType = StringClass, .reference = 1, .string.value = set->varName };
|
||||||
|
Variable_t* args[2] = { &varName, curRes };
|
||||||
|
callMemberFunctionDirect(set->setVar, "set", args, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
removePendingReference(curRes);
|
||||||
|
removePendingReference(set->setVar);
|
||||||
|
|
||||||
|
// TODO: add non-top level sets
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* eval(Operator_t* ops, u32 len, u8 ret) {
|
||||||
|
Variable_t* curRes = NULL;
|
||||||
|
Operator_t* curOp = NULL;
|
||||||
|
Callback_SetVar_t set = { 0 };
|
||||||
|
for (u32 i = 0; i < len; i++) {
|
||||||
|
Operator_t* cur = &ops[i];
|
||||||
|
|
||||||
|
if (cur->token == CallArgs)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cur->token == EquationSeperator) {
|
||||||
|
scriptCurrentLine = cur->lineNumber;
|
||||||
|
if (set.hasBeenNoticed == 1)
|
||||||
|
runtimeVariableEdit(&set, curRes);
|
||||||
|
else
|
||||||
|
removePendingReference(curRes);
|
||||||
|
|
||||||
|
memset(&set, 0, sizeof(Callback_SetVar_t));
|
||||||
|
curRes = NULL;
|
||||||
|
curOp = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curRes == NULL) {
|
||||||
|
if (cur->token != Variable && cur->token != BetweenBrackets) {
|
||||||
|
SCRIPT_FATAL_ERR("First token is not a variable");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
curRes = opToVar(cur, &set, (len - i) > 1);
|
||||||
|
if (!curRes) {
|
||||||
|
if ((set.varName != NULL || set.idxVar != NULL) && set.hasBeenNoticed == 0) {
|
||||||
|
set.hasBeenNoticed = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curOp == NULL) {
|
||||||
|
if (cur->token != Variable && cur->token != BetweenBrackets) {
|
||||||
|
curOp = cur;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCRIPT_FATAL_ERR("Expected operator");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* rightSide = opToVar(cur, &set, (len - i) > 1);
|
||||||
|
if (!rightSide)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
// Issue lies here for freeing issues, curRes is corrupted
|
||||||
|
Variable_t* result = callMemberFunctionDirect(curRes, curOp->tokenStr, &rightSide, 1);
|
||||||
|
// Free old values
|
||||||
|
|
||||||
|
removePendingReference(curRes);
|
||||||
|
removePendingReference(rightSide);
|
||||||
|
rightSide = NULL;
|
||||||
|
curOp = NULL;
|
||||||
|
|
||||||
|
curRes = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.hasBeenNoticed == 1) {
|
||||||
|
runtimeVariableEdit(&set, curRes);
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
else if (!ret) {
|
||||||
|
removePendingReference(curRes);
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
return curRes;
|
||||||
|
}
|
||||||
19
source/script/eval.h
Normal file
19
source/script/eval.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "model.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct {
|
||||||
|
u8 isTopLevel : 1;
|
||||||
|
u8 hasBeenNoticed : 1;
|
||||||
|
u8 hasVarName : 1;
|
||||||
|
};
|
||||||
|
Variable_t* setVar;
|
||||||
|
char* varName;
|
||||||
|
Function_t* idxVar;
|
||||||
|
} Callback_SetVar_t;
|
||||||
|
|
||||||
|
Variable_t* eval(Operator_t* ops, u32 len, u8 ret);
|
||||||
|
void setStaticVars(Vector_t* vec);
|
||||||
|
void initRuntimeVars();
|
||||||
|
void exitRuntimeVars();
|
||||||
|
void runtimeVariableEdit(Callback_SetVar_t* set, Variable_t* curRes);
|
||||||
67
source/script/functionClass.c
Normal file
67
source/script/functionClass.c
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include "functionClass.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "model.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
Function_t* getFunctionValue(Variable_t* var) {
|
||||||
|
if (var->variableType != FunctionClass)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
FunctionClass_t* a = &var->function;
|
||||||
|
|
||||||
|
if (a->builtIn)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &a->function;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function_t createEmptyFunction() {
|
||||||
|
Function_t a = { 0 };
|
||||||
|
a.operations = newVec(sizeof(Operator_t), 0);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will NOT copy the Function, the pointer is taken as-is. Set as NULL to make it builtin
|
||||||
|
FunctionClass_t createFunctionClass(Function_t in, ClassFunctionTableEntry_t *builtIn) {
|
||||||
|
FunctionClass_t a = { 0 };
|
||||||
|
if (!builtIn) {
|
||||||
|
a.function = in;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a.builtIn = 1;
|
||||||
|
a.builtInPtr = builtIn;
|
||||||
|
a.len = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionClass_t* creteFunctionClassPtr(Function_t in, ClassFunctionTableEntry_t* builtIn) {
|
||||||
|
FunctionClass_t* a = malloc(sizeof(FunctionClass_t));
|
||||||
|
*a = createFunctionClass(in, builtIn);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function_t* createFunctionPtrFromFunction(Function_t in) {
|
||||||
|
Function_t* f = malloc(sizeof(Function_t));
|
||||||
|
*f = in;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions are always readonly
|
||||||
|
Variable_t newFunctionVariable(FunctionClass_t func) {
|
||||||
|
Variable_t var = { .variableType = FunctionClass, .readOnly = 1, .function = func };
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
int countTokens(Function_t *func, u8 toCount) {
|
||||||
|
Operator_t* ops = func->operations.data;
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < func->operations.count; i++) {
|
||||||
|
if (ops[i].token == toCount) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
8
source/script/functionClass.h
Normal file
8
source/script/functionClass.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "model.h"
|
||||||
|
|
||||||
|
Function_t createEmptyFunction();
|
||||||
|
Function_t* createFunctionPtrFromFunction(Function_t in);
|
||||||
|
Variable_t newFunctionVariable(FunctionClass_t func);
|
||||||
|
FunctionClass_t createFunctionClass(Function_t in, ClassFunctionTableEntry_t* builtIn);
|
||||||
|
int countTokens(Function_t* func, u8 toCount);
|
||||||
@@ -1,529 +0,0 @@
|
|||||||
#include "types.h"
|
|
||||||
#include "args.h"
|
|
||||||
#include "variables.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include "../gfx/gfx.h"
|
|
||||||
#include <mem/heap.h>
|
|
||||||
#include "lexer.h"
|
|
||||||
|
|
||||||
#include <storage/nx_sd.h>
|
|
||||||
#include "../fs/fsutils.h"
|
|
||||||
#include "../gfx/gfxutils.h"
|
|
||||||
#include "../hid/hid.h"
|
|
||||||
#include <utils/util.h>
|
|
||||||
#include "../fs/fscopy.h"
|
|
||||||
#include "../storage/mountmanager.h"
|
|
||||||
#include "../storage/emummc.h"
|
|
||||||
#include "../fs/readers/folderReader.h"
|
|
||||||
#include "../utils/utils.h"
|
|
||||||
#include "../keys/keys.h"
|
|
||||||
#include "../storage/emmcfile.h"
|
|
||||||
#include "../keys/nca.h"
|
|
||||||
#include "../keys/save.h"
|
|
||||||
#include "../tegraexplorer/tconf.h"
|
|
||||||
|
|
||||||
#define scriptFunction(name) Variable_t name(scriptCtx_t *ctx, Variable_t *vars, u32 varLen)
|
|
||||||
|
|
||||||
#define varInt(i) newVar(IntType, 0, i)
|
|
||||||
#define varStr(s) newVar(StringType, 1, .stringType = s)
|
|
||||||
|
|
||||||
scriptFunction(funcIf) {
|
|
||||||
setCurIndentInstruction(ctx, (vars[0].integerType == 0), 0, -1);
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcPrint) {
|
|
||||||
for (u32 i = 0; i < varLen; i++) {
|
|
||||||
if (vars[i].varType == IntType)
|
|
||||||
gfx_printf("%d", vars[i].integerType);
|
|
||||||
else if (vars[i].varType == StringType)
|
|
||||||
gfx_printf("%s", vars[i].stringType);
|
|
||||||
else if (vars[i].varType == IntArrayType) {
|
|
||||||
gfx_printf("[");
|
|
||||||
int* v = vecGetArray(int*, vars[i].vectorType);
|
|
||||||
for (u32 j = 0; j < vars[i].vectorType.count; j++)
|
|
||||||
gfx_printf((j + 1 == vars[i].vectorType.count) ? "%d" : "%d, ", v[j]);
|
|
||||||
gfx_printf("]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcPrintln) {
|
|
||||||
funcPrint(ctx, vars, varLen);
|
|
||||||
gfx_printf("\n");
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcWhile) {
|
|
||||||
setCurIndentInstruction(ctx, (vars[0].integerType == 0), 0, ctx->startEquation);
|
|
||||||
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcElse) {
|
|
||||||
indentInstructor_t* curInstruction = getCurIndentInstruction(ctx);
|
|
||||||
setCurIndentInstruction(ctx, !curInstruction->skip, 0, -1);
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcLen) {
|
|
||||||
if (vars[0].varType >= IntArrayType && vars[0].varType <= ByteArrayType)
|
|
||||||
return IntVal(vars[0].vectorType.count);
|
|
||||||
else if (vars[0].varType == StringType) {
|
|
||||||
if (vars[0].stringType != NULL)
|
|
||||||
return IntVal(strlen(vars[0].stringType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrVar(ERRINVALIDTYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcMakeByteArray){
|
|
||||||
u8 *buff = malloc(vars[0].vectorType.count);
|
|
||||||
vecDefArray(int*, entries, vars[0].vectorType);
|
|
||||||
for (int i = 0; i < vars[0].vectorType.count; i++)
|
|
||||||
buff[i] = (u8)(entries[i] & 0xFF);
|
|
||||||
|
|
||||||
Vector_t v = vecFromArray(buff, vars[0].vectorType.count, sizeof(u8));
|
|
||||||
return newVar(ByteArrayType, 1, .vectorType = v);
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcSetPixel){
|
|
||||||
u32 color = 0xFF000000 | ((vars[2].integerType & 0xFF) << 16) | ((vars[3].integerType & 0xFF) << 8) | (vars[4].integerType & 0xFF);
|
|
||||||
gfx_set_pixel_horz(vars[0].integerType, vars[1].integerType, color);
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcFileExists){
|
|
||||||
return newVar(IntType, 0, FileExists(vars[0].stringType));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str (Path)
|
|
||||||
scriptFunction(funcReadFile){
|
|
||||||
u32 fSize = 0;
|
|
||||||
u8 *buff = sd_file_read(vars[0].stringType, &fSize);
|
|
||||||
if (buff == NULL)
|
|
||||||
return ErrVar(ERRFATALFUNCFAIL);
|
|
||||||
|
|
||||||
Vector_t vec = vecFromArray(buff, fSize, sizeof(u8));
|
|
||||||
return newVar(ByteArrayType, 1, .vectorType = vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str (Path), vector(Byte) (toWrite)
|
|
||||||
scriptFunction(funcWriteFile){
|
|
||||||
return newVar(IntType, 0, sd_save_to_file(vars[1].vectorType.data, vars[1].vectorType.count, vars[0].stringType));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: vector(Byte)
|
|
||||||
scriptFunction(funcByteToStr){
|
|
||||||
char *str = calloc(vars[0].vectorType.count + 1, 1);
|
|
||||||
memcpy(str, vars[0].vectorType.data, vars[0].vectorType.count);
|
|
||||||
return newVar(StringType, 1, .stringType = str);
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcReturn){
|
|
||||||
if (ctx->indentIndex > 0){
|
|
||||||
vecDefArray(indentInstructor_t*, instructors, ctx->indentInstructors);
|
|
||||||
for (int i = ctx->indentIndex - 1; i >= 0; i--){
|
|
||||||
indentInstructor_t ins = instructors[i];
|
|
||||||
if (ins.active && ins.jump && ins.function){
|
|
||||||
ctx->curPos = ins.jumpLoc - 1;
|
|
||||||
ins.active = 0;
|
|
||||||
ctx->indentIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcExit){
|
|
||||||
return ErrVar(ERRESCSCRIPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
scriptFunction(funcContinue){
|
|
||||||
if (ctx->indentIndex > 0){
|
|
||||||
vecDefArray(indentInstructor_t*, instructors, ctx->indentInstructors);
|
|
||||||
for (int i = ctx->indentIndex - 1; i >= 0; i--){
|
|
||||||
indentInstructor_t ins = instructors[i];
|
|
||||||
if (ins.active && ins.jump && !ins.function){
|
|
||||||
ctx->curPos = ins.jumpLoc - 1;
|
|
||||||
ins.active = 0;
|
|
||||||
ctx->indentIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Args: Int, Int
|
|
||||||
scriptFunction(funcSetPrintPos){
|
|
||||||
if (vars[0].integerType > 78 || vars[0].integerType < 0 || vars[1].integerType > 42 || vars[1].integerType < 0)
|
|
||||||
return ErrVar(ERRFATALFUNCFAIL);
|
|
||||||
|
|
||||||
gfx_con_setpos(vars[0].integerType * 16, vars[1].integerType * 16);
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcClearScreen){
|
|
||||||
gfx_clearscreen();
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
int validRanges[] = {
|
|
||||||
1279,
|
|
||||||
719,
|
|
||||||
1279,
|
|
||||||
719
|
|
||||||
};
|
|
||||||
|
|
||||||
// Args: Int, Int, Int, Int, Int
|
|
||||||
scriptFunction(funcDrawBox){
|
|
||||||
for (int i = 0; i < ARR_LEN(validRanges); i++){
|
|
||||||
if (vars[i].integerType > validRanges[i] || vars[i].integerType < 0)
|
|
||||||
return ErrVar(ERRFATALFUNCFAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
gfx_box(vars[0].integerType, vars[1].integerType, vars[2].integerType, vars[3].integerType, vars[4].integerType);
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *name;
|
|
||||||
u32 color;
|
|
||||||
} ColorCombo_t;
|
|
||||||
|
|
||||||
ColorCombo_t combos[] = {
|
|
||||||
{"RED", COLOR_RED},
|
|
||||||
{"ORANGE", COLOR_ORANGE},
|
|
||||||
{"YELLOW", COLOR_YELLOW},
|
|
||||||
{"GREEN", COLOR_GREEN},
|
|
||||||
{"BLUE", COLOR_BLUE},
|
|
||||||
{"VIOLET", COLOR_VIOLET},
|
|
||||||
{"GREY", COLOR_GREY},
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 GetColor(char *color){
|
|
||||||
for (int i = 0; i < ARR_LEN(combos); i++){
|
|
||||||
if (!strcmp(combos[i].name, color)){
|
|
||||||
return combos[i].color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return COLOR_WHITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcSetColor){
|
|
||||||
SETCOLOR(GetColor(vars[0].stringType), COLOR_DEFAULT);
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcPause){
|
|
||||||
return newVar(IntType, 0, hidWait()->buttons);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Int
|
|
||||||
scriptFunction(funcWait){
|
|
||||||
u32 timer = get_tmr_ms();
|
|
||||||
while (timer + vars[0].integerType > get_tmr_ms()){
|
|
||||||
gfx_printf("<Wait %d seconds> \r", (vars[0].integerType - (get_tmr_ms() - timer)) / 1000);
|
|
||||||
hidRead();
|
|
||||||
}
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcGetVer){
|
|
||||||
int *arr = malloc(3 * sizeof(int));
|
|
||||||
arr[0] = LP_VER_MJ;
|
|
||||||
arr[1] = LP_VER_MN;
|
|
||||||
arr[2] = LP_VER_BF;
|
|
||||||
Vector_t res = vecFromArray(arr, 3, sizeof(int));
|
|
||||||
return newVar(IntArrayType, 1, .vectorType = res);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Args: vec(str), int, (optional) vec(str)
|
|
||||||
scriptFunction(funcMakeMenu){
|
|
||||||
if (varLen == 3 && vars[2].vectorType.count != vars[0].vectorType.count)
|
|
||||||
return ErrVar(ERRSYNTAX);
|
|
||||||
|
|
||||||
Vector_t menuEntries = newVec(sizeof(MenuEntry_t), vars[0].vectorType.count);
|
|
||||||
vecDefArray(char**, names, vars[0].vectorType);
|
|
||||||
char **colors;
|
|
||||||
if (varLen >= 3)
|
|
||||||
colors = vecGetArray(char**, vars[2].vectorType);
|
|
||||||
|
|
||||||
int *options;
|
|
||||||
if (varLen == 4)
|
|
||||||
options = vecGetArray(int*, vars[3].vectorType);
|
|
||||||
|
|
||||||
for (int i = 0; i < vars[0].vectorType.count; i++){
|
|
||||||
u32 color = COLORTORGB(((varLen >= 3) ? GetColor(colors[i]) : COLOR_WHITE));
|
|
||||||
MenuEntry_t a = {.optionUnion = color, .name = names[i]};
|
|
||||||
|
|
||||||
if (varLen == 4){
|
|
||||||
a.skip = (options[i] & 1) ? 1 : 0;
|
|
||||||
a.hide = (options[i] & 2) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vecAddElem(&menuEntries, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
int res = newMenu(&menuEntries, vars[1].integerType, 78, 10, ENABLEB | ALWAYSREDRAW, menuEntries.count);
|
|
||||||
vecFree(menuEntries);
|
|
||||||
return varInt(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str, Str
|
|
||||||
scriptFunction(funcCombinePath){
|
|
||||||
if (varLen <= 1)
|
|
||||||
return NullVar;
|
|
||||||
|
|
||||||
for (int i = 0; i < varLen; i++){
|
|
||||||
if (vars[i].varType != StringType)
|
|
||||||
return ErrVar(ERRINVALIDTYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *res = CpyStr(vars[0].stringType);
|
|
||||||
|
|
||||||
for (int i = 1; i < varLen; i++){
|
|
||||||
char *temp = CombinePaths(res, vars[i].stringType);
|
|
||||||
free(res);
|
|
||||||
res = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return varStr(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcEscFolder){
|
|
||||||
return newVar(StringType, 1, .stringType = EscapeFolder(vars[0].stringType));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str, Str
|
|
||||||
scriptFunction(funcFileMove){
|
|
||||||
return varInt(f_rename(vars[0].stringType, vars[1].stringType));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str, Str
|
|
||||||
scriptFunction(funcFileCopy){
|
|
||||||
return varInt(FileCopy(vars[0].stringType, vars[1].stringType, COPY_MODE_PRINT).err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcMmcConnect){
|
|
||||||
int res = 0;
|
|
||||||
if (!strcmp(vars[0].stringType, "SYSMMC"))
|
|
||||||
res = connectMMC(MMC_CONN_EMMC);
|
|
||||||
else if (!strcmp(vars[0].stringType, "EMUMMC") && emu_cfg.enabled)
|
|
||||||
res = connectMMC(MMC_CONN_EMUMMC);
|
|
||||||
else
|
|
||||||
return ErrVar(ERRFATALFUNCFAIL);
|
|
||||||
|
|
||||||
return varInt(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcMmcMount){
|
|
||||||
if (!TConf.keysDumped)
|
|
||||||
return ErrVar(ERRFATALFUNCFAIL);
|
|
||||||
|
|
||||||
return varInt((mountMMCPart(vars[0].stringType).err));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcMkdir){
|
|
||||||
return varInt((f_mkdir(vars[0].stringType)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcReadDir){
|
|
||||||
int res = 0;
|
|
||||||
Vector_t files = ReadFolder(vars[0].stringType, &res);
|
|
||||||
if (res){
|
|
||||||
clearFileVector(&files);
|
|
||||||
return ErrVar(ERRFATALFUNCFAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
vecDefArray(FSEntry_t*, fsEntries, files);
|
|
||||||
|
|
||||||
Vector_t fileNames = newVec(sizeof(char*), files.count);
|
|
||||||
Vector_t fileProperties = newVec(sizeof(int), files.count);
|
|
||||||
|
|
||||||
for (int i = 0; i < files.count; i++){
|
|
||||||
vecAddElem(&fileNames, fsEntries[i].name);
|
|
||||||
int isFolder = fsEntries[i].isDir;
|
|
||||||
vecAddElem(&fileProperties, isFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
vecFree(files);
|
|
||||||
|
|
||||||
dictVectorAdd(&ctx->varDict, newDict(CpyStr("fileProperties"), (newVar(IntArrayType, 1, .vectorType = fileProperties))));
|
|
||||||
|
|
||||||
return newVar(StringArrayType, 1, .vectorType = fileNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str, Str
|
|
||||||
scriptFunction(funcCopyDir){
|
|
||||||
return varInt((FolderCopy(vars[0].stringType, vars[1].stringType).err));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcDelDir){
|
|
||||||
return varInt((FolderDelete(vars[0].stringType).err));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcDelFile){
|
|
||||||
return varInt((f_unlink(vars[0].stringType)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str, Str
|
|
||||||
scriptFunction(funcMmcDump){
|
|
||||||
return varInt((DumpOrWriteEmmcPart(vars[0].stringType, vars[1].stringType, 0, 1).err));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str, Str, Int
|
|
||||||
scriptFunction(funcMmcRestore){
|
|
||||||
return varInt((DumpOrWriteEmmcPart(vars[0].stringType, vars[1].stringType, 1, vars[2].integerType).err));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcGetNcaType){
|
|
||||||
if (!TConf.keysDumped)
|
|
||||||
return ErrVar(ERRFATALFUNCFAIL);
|
|
||||||
|
|
||||||
return varInt((GetNcaType(vars[0].stringType)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcSignSave){
|
|
||||||
if (!TConf.keysDumped)
|
|
||||||
return ErrVar(ERRFATALFUNCFAIL);
|
|
||||||
|
|
||||||
return varInt((saveCommit(vars[0].stringType).err));
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFunction(funcGetMs){
|
|
||||||
return varInt(get_tmr_ms());
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int launch_payload(char *path);
|
|
||||||
|
|
||||||
// Args: Str
|
|
||||||
scriptFunction(funcLaunchPayload){
|
|
||||||
return varInt(launch_payload(vars[0].stringType));
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 fiveInts[] = {IntType, IntType, IntType, IntType, IntType};
|
|
||||||
u8 singleIntArray[] = { IntArrayType };
|
|
||||||
u8 singleInt[] = { IntType };
|
|
||||||
u8 singleAny[] = { varArgs };
|
|
||||||
u8 singleStr[] = { StringType };
|
|
||||||
u8 singleByteArr[] = { ByteArrayType };
|
|
||||||
u8 StrByteVec[] = { StringType, ByteArrayType};
|
|
||||||
u8 MenuArgs[] = { StringArrayType, IntType, StringArrayType, IntArrayType};
|
|
||||||
u8 twoStrings[] = { StringType, StringType };
|
|
||||||
u8 mmcReadWrite[] = { StringType, StringType, IntType};
|
|
||||||
|
|
||||||
functionStruct_t scriptFunctions[] = {
|
|
||||||
{"if", funcIf, 1, singleInt},
|
|
||||||
{"print", funcPrint, varArgs, NULL},
|
|
||||||
{"println", funcPrintln, varArgs, NULL},
|
|
||||||
{"while", funcWhile, 1, singleInt},
|
|
||||||
{"else", funcElse, 0, NULL},
|
|
||||||
{"len", funcLen, 1, singleAny},
|
|
||||||
{"byte", funcMakeByteArray, 1, singleIntArray},
|
|
||||||
{"setPixel", funcSetPixel, 5, fiveInts},
|
|
||||||
{"fileRead", funcReadFile, 1, singleStr},
|
|
||||||
{"fileWrite", funcWriteFile, 2, StrByteVec},
|
|
||||||
{"fileExists", funcFileExists, 1, singleStr},
|
|
||||||
{"bytesToStr", funcByteToStr, 1, singleByteArr},
|
|
||||||
{"return", funcReturn, 0, NULL},
|
|
||||||
{"exit", funcExit, 0, NULL},
|
|
||||||
//{"continue", funcContinue, 0, NULL},
|
|
||||||
{"printPos", funcSetPrintPos, 2, fiveInts},
|
|
||||||
{"clearscreen", funcClearScreen, 0, NULL},
|
|
||||||
{"drawBox", funcDrawBox, 5, fiveInts},
|
|
||||||
{"color", funcSetColor, 1, singleStr},
|
|
||||||
{"pause", funcPause, 0, NULL},
|
|
||||||
{"wait", funcWait, 1, singleInt},
|
|
||||||
{"version", funcGetVer, 0, NULL},
|
|
||||||
{"menu", funcMakeMenu, 2, MenuArgs}, // for the optional arg
|
|
||||||
{"menu", funcMakeMenu, 3, MenuArgs},
|
|
||||||
{"menu", funcMakeMenu, 4, MenuArgs},
|
|
||||||
{"pathCombine", funcCombinePath, varArgs, NULL},
|
|
||||||
{"pathEscFolder", funcEscFolder, 1, singleStr},
|
|
||||||
{"fileMove", funcFileMove, 2, twoStrings},
|
|
||||||
{"fileCopy", funcFileCopy, 2, twoStrings},
|
|
||||||
{"fileDel", funcDelFile, 1, singleStr},
|
|
||||||
{"mmcConnect", funcMmcConnect, 1, singleStr},
|
|
||||||
{"mmcMount", funcMmcMount, 1, singleStr},
|
|
||||||
{"mkdir", funcMkdir, 1, singleStr},
|
|
||||||
{"dirRead", funcReadDir, 1, singleStr},
|
|
||||||
{"dirCopy", funcCopyDir, 2, twoStrings},
|
|
||||||
{"dirDel", funcDelDir, 1, singleStr},
|
|
||||||
{"mmcDump", funcMmcDump, 2, mmcReadWrite},
|
|
||||||
{"mmcRestore", funcMmcRestore, 3, mmcReadWrite},
|
|
||||||
{"ncaGetType", funcGetNcaType, 1, singleStr},
|
|
||||||
{"saveSign", funcSignSave, 1, singleStr},
|
|
||||||
{"timerMs", funcGetMs, 0, NULL},
|
|
||||||
{"launchPayload", funcLaunchPayload, 1, singleStr},
|
|
||||||
// Left from old: keyboard(?)
|
|
||||||
};
|
|
||||||
|
|
||||||
Variable_t executeFunction(scriptCtx_t* ctx, char* func_name, lexarToken_t *start, u32 len) {
|
|
||||||
Vector_t args = { 0 };
|
|
||||||
|
|
||||||
if (len > 0) {
|
|
||||||
args = extractVars(ctx, start, len);
|
|
||||||
Variable_t* vars = vecGetArray(Variable_t*, args);
|
|
||||||
for (int i = 0; i < args.count; i++) {
|
|
||||||
if (vars[i].varType == ErrType)
|
|
||||||
return vars[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variable_t* vars = vecGetArray(Variable_t*, args);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < ARRAY_SIZE(scriptFunctions); i++) {
|
|
||||||
if (scriptFunctions[i].argCount == args.count || scriptFunctions[i].argCount == varArgs) {
|
|
||||||
if (!strcmp(scriptFunctions[i].key, func_name)) {
|
|
||||||
if (scriptFunctions[i].argCount != varArgs && scriptFunctions[i].argCount != 0) {
|
|
||||||
u8 argsMatch = 1;
|
|
||||||
for (u32 j = 0; j < args.count; j++) {
|
|
||||||
if (vars[j].varType != scriptFunctions[i].typeArray[j] && scriptFunctions[i].typeArray[j] != varArgs) {
|
|
||||||
argsMatch = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!argsMatch)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Variable_t ret = scriptFunctions[i].value(ctx, vars, args.count);
|
|
||||||
freeVariableVector(&args);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variable_t* var = dictVectorFind(&ctx->varDict, func_name);
|
|
||||||
if (var != NULL) {
|
|
||||||
if (var->varType == JumpType) {
|
|
||||||
setCurIndentInstruction(ctx, 0, 1, ctx->curPos);
|
|
||||||
ctx->curPos = var->integerType - 1;
|
|
||||||
return NullVar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrVar(ERRNOFUNC);
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "variables.h"
|
|
||||||
|
|
||||||
Variable_t executeFunction(scriptCtx_t* ctx, char* func_name, lexarToken_t* start, u32 len);
|
|
||||||
26
source/script/garbageCollector.c
Normal file
26
source/script/garbageCollector.c
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include "model.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "garbageCollector.h"
|
||||||
|
|
||||||
|
void modReference(Variable_t* ref, u8 add) {
|
||||||
|
if (ref == NULL || ref->gcDoNotFree)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (add) {
|
||||||
|
ref->tagCount++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ref->tagCount--;
|
||||||
|
if (ref->tagCount <= 0) {
|
||||||
|
// TODO: move to parser.c
|
||||||
|
if (ref->variableType == FunctionClass && ref->function.builtIn && ref->function.origin != NULL)
|
||||||
|
modReference(ref->function.origin, 0);
|
||||||
|
|
||||||
|
if (ref->variableType == SolvedArrayReferenceClass)
|
||||||
|
modReference(ref->solvedArray.arrayClassReference, 0);
|
||||||
|
|
||||||
|
freeVariable(&ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
source/script/garbageCollector.h
Normal file
8
source/script/garbageCollector.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "model.h"
|
||||||
|
|
||||||
|
//void removePendingReference(Variable_t* ref);
|
||||||
|
|
||||||
|
void modReference(Variable_t* ref, u8 add);
|
||||||
|
|
||||||
|
#define removePendingReference(ref) modReference(ref, 0)
|
||||||
|
#define addPendingReference(ref) modReference(ref, 1)
|
||||||
297
source/script/genericClass.c
Normal file
297
source/script/genericClass.c
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
#include "genericClass.h"
|
||||||
|
#include "model.h"
|
||||||
|
#include "intClass.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "eval.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "garbageCollector.h"
|
||||||
|
#include "StringClass.h"
|
||||||
|
#include "arrayClass.h"
|
||||||
|
#include "arrayReferenceClass.h"
|
||||||
|
#include "functionClass.h"
|
||||||
|
#include "scriptError.h"
|
||||||
|
#include "saveClass.h"
|
||||||
|
#include "unsolvedArrayClass.h"
|
||||||
|
#include "else.h"
|
||||||
|
#include "dictionaryClass.h"
|
||||||
|
|
||||||
|
Variable_t* copyVariableToPtr(Variable_t var) {
|
||||||
|
Variable_t* a = malloc(sizeof(Variable_t));
|
||||||
|
*a = var;
|
||||||
|
a->tagCount = 0;
|
||||||
|
addPendingReference(a);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemberGetters_t memberGetters[] = {
|
||||||
|
{IntClass, getIntegerMember},
|
||||||
|
{StringClass, getStringMember},
|
||||||
|
{IntArrayClass, getArrayMember},
|
||||||
|
{StringArrayClass, getArrayMember},
|
||||||
|
{ByteArrayClass, getArrayMember},
|
||||||
|
{SolvedArrayReferenceClass, getArrayReferenceMember},
|
||||||
|
{UnresolvedArrayClass, getUnsolvedArrayMember},
|
||||||
|
{ElseClass, getElseMember},
|
||||||
|
{DictionaryClass, getDictMember},
|
||||||
|
#ifndef WIN32
|
||||||
|
{SaveClass, getSaveMember},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
Variable_t* genericGet(Variable_t* var, CallArgs_t* ref) {
|
||||||
|
if (ref->extraAction == ActionExtraMemberName) {
|
||||||
|
for (u32 i = 0; i < ARRAY_SIZE(memberGetters); i++) {
|
||||||
|
if (var->variableType == memberGetters[i].classType) {
|
||||||
|
Variable_t member = memberGetters[i].func(var, ref->extra);
|
||||||
|
if (member.variableType == None)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (member.variableType == ReferenceType) {
|
||||||
|
return member.referenceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
addPendingReference(var); // So caller doesn't fall out of scope. Don't forget to free!
|
||||||
|
return copyVariableToPtr(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FATAL_ERR("Did not find member '%s'", ref->extra);
|
||||||
|
}
|
||||||
|
else if (ref->extraAction == ActionExtraArrayIndex) {
|
||||||
|
Function_t* idx = ref->extra;
|
||||||
|
Variable_t *solvedIdx = eval(idx->operations.data, idx->operations.count, 1);
|
||||||
|
|
||||||
|
if (solvedIdx->variableType != IntClass) {
|
||||||
|
SCRIPT_FATAL_ERR("Index is not an integer");
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* res = callMemberFunctionDirect(var, "get", &solvedIdx, 1);
|
||||||
|
removePendingReference(solvedIdx);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FATAL_ERR("???");
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* genericCallDirect(Variable_t* var, Variable_t** args, u8 len) {
|
||||||
|
if (var->variableType != FunctionClass){
|
||||||
|
SCRIPT_FATAL_ERR("Call on non function class");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var->function.builtIn) {
|
||||||
|
for (u32 i = 0; i < var->function.len; i++) {
|
||||||
|
if (var->function.builtInPtr[i].argCount == len || var->function.builtInPtr[i].argCount == VARARGCOUNT) {
|
||||||
|
int valid = 1;
|
||||||
|
if (var->function.builtInPtr[i].argCount != VARARGCOUNT) {
|
||||||
|
for (u32 j = 0; j < var->function.builtInPtr[i].argCount; j++) {
|
||||||
|
if (var->function.builtInPtr[i].argTypes[j] != args[j]->variableType && var->function.builtInPtr[i].argTypes[j] != VARARGCOUNT) {
|
||||||
|
valid = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
return var->function.builtInPtr[i].func(var->function.origin, args, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Variable_t *ret = eval(var->function.function.operations.data, var->function.function.operations.count, 1);
|
||||||
|
if (ret == NULL)
|
||||||
|
return NULL;
|
||||||
|
removePendingReference(ret);
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FATAL_ERR("Arguments do not match function defenition(s)");
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* genericCall(Variable_t* var, CallArgs_t* ref) {
|
||||||
|
if (var->variableType != FunctionClass){
|
||||||
|
SCRIPT_FATAL_ERR("Call on non function class");
|
||||||
|
}
|
||||||
|
Function_t* f = ref->extra;
|
||||||
|
if (var->function.builtIn) {
|
||||||
|
if (f->operations.count == 0) {
|
||||||
|
return genericCallDirect(var, NULL, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//Vector_t argsHolder = newVec(sizeof(Variable_t*), 1);
|
||||||
|
Variable_t** argsHolder = NULL;
|
||||||
|
if (var->function.builtInPtr->argCount != 0)
|
||||||
|
argsHolder = malloc(sizeof(Variable_t*) * var->function.builtInPtr->argCount);
|
||||||
|
int argCount = 0;
|
||||||
|
int lasti = 0;
|
||||||
|
Operator_t* ops = f->operations.data;
|
||||||
|
|
||||||
|
int tooManyArgs = 0;
|
||||||
|
|
||||||
|
// Loops trough the function to get all args out
|
||||||
|
for (int i = 0; i < f->operations.count; i++) {
|
||||||
|
if (ops[i].token == EquationSeperator || i + 1 == f->operations.count) {
|
||||||
|
if (i + 1 == f->operations.count)
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (argCount == var->function.builtInPtr->argCount) {
|
||||||
|
tooManyArgs = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var->function.firstArgAsFunction && argCount == 0) {
|
||||||
|
Function_t f = { .operations = vecFromArray(&ops[lasti], i - lasti, sizeof(Operator_t)) };
|
||||||
|
Variable_t var = newFunctionVariable(createFunctionClass(f, NULL));
|
||||||
|
var.reference = 1;
|
||||||
|
Variable_t* varPtr = copyVariableToPtr(var);
|
||||||
|
//vecAdd(&argsHolder, varPtr);
|
||||||
|
argsHolder[argCount++] = varPtr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Variable_t* var = eval(&ops[lasti], i - lasti, 1);
|
||||||
|
if (var == NULL)
|
||||||
|
return NULL; // maybe free first?
|
||||||
|
|
||||||
|
//vecAdd(&argsHolder, var);
|
||||||
|
argsHolder[argCount++] = var;
|
||||||
|
}
|
||||||
|
|
||||||
|
lasti = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* res = NULL;
|
||||||
|
|
||||||
|
if (!tooManyArgs)
|
||||||
|
res = genericCallDirect(var, argsHolder, argCount);
|
||||||
|
else {
|
||||||
|
SCRIPT_FATAL_ERR("Too many args provided (got more than %d)", argCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < argCount; i++)
|
||||||
|
removePendingReference(argsHolder[i]);
|
||||||
|
|
||||||
|
//vecForEach(Variable_t**, tofree, (&argsHolder))
|
||||||
|
// removePendingReference(*tofree);
|
||||||
|
|
||||||
|
FREE(argsHolder);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (f->operations.count){
|
||||||
|
if (eval(f->operations.data, f->operations.count, 0) == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eval(var->function.function.operations.data, var->function.function.operations.count, 0) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add staticStorage
|
||||||
|
Variable_t getGenericFunctionMember(Variable_t* var, char* memberName, ClassFunctionTableEntry_t* entries, u8 len) {
|
||||||
|
Variable_t newVar = {.readOnly = 1, .variableType = FunctionClass};
|
||||||
|
newVar.function.origin = var;
|
||||||
|
newVar.function.builtIn = 1;
|
||||||
|
for (u32 i = 0; i < len; i++) {
|
||||||
|
if (!strcmp(entries[i].name, memberName)) {
|
||||||
|
newVar.function.builtInPtr = &entries[i];
|
||||||
|
|
||||||
|
u32 j = i;
|
||||||
|
for (; j < len && !strcmp(entries[j].name, memberName); j++);
|
||||||
|
newVar.function.len = j - i;
|
||||||
|
|
||||||
|
return newVar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Variable_t){ 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* callMemberFunction(Variable_t* var, char* memberName, CallArgs_t* args) {
|
||||||
|
for (u32 i = 0; i < ARRAY_SIZE(memberGetters); i++) {
|
||||||
|
if (var->variableType == memberGetters[i].classType) {
|
||||||
|
Variable_t funcRef = memberGetters[i].func(var, memberName);
|
||||||
|
if (funcRef.variableType == None) {
|
||||||
|
SCRIPT_FATAL_ERR("Did not find member '%s'", memberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* ptr = &funcRef;
|
||||||
|
if (funcRef.variableType == ReferenceType) {
|
||||||
|
ptr = funcRef.referenceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return genericCall(ptr, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FATAL_ERR("Could not find function table for given type");
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* callMemberFunctionDirect(Variable_t* var, char* memberName, Variable_t** args, u8 argsLen) {
|
||||||
|
for (u32 i = 0; i < ARRAY_SIZE(memberGetters); i++) {
|
||||||
|
if (var->variableType == memberGetters[i].classType) {
|
||||||
|
Variable_t funcRef = memberGetters[i].func(var, memberName);
|
||||||
|
if (funcRef.variableType == None) {
|
||||||
|
SCRIPT_FATAL_ERR("Did not find member '%s'", memberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t* ptr = &funcRef;
|
||||||
|
if (funcRef.variableType == ReferenceType) {
|
||||||
|
ptr = funcRef.referenceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return genericCallDirect(ptr, args, argsLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FATAL_ERR("Could not find function table for given type");
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeVariableInternal(Variable_t* referencedTarget) {
|
||||||
|
switch (referencedTarget->variableType) {
|
||||||
|
case StringClass:
|
||||||
|
FREE(referencedTarget->string.value);
|
||||||
|
break;
|
||||||
|
case StringArrayClass:
|
||||||
|
vecForEach(char**, stringsInArray, (&referencedTarget->solvedArray.vector)) {
|
||||||
|
FREE(*stringsInArray);
|
||||||
|
}
|
||||||
|
case ByteArrayClass:
|
||||||
|
case IntArrayClass:
|
||||||
|
vecFree(referencedTarget->solvedArray.vector);
|
||||||
|
break;
|
||||||
|
case DictionaryClass:;
|
||||||
|
vecForEach(Dict_t*, dict, (&referencedTarget->dictionary.vector)) {
|
||||||
|
modReference(dict->var, 0);
|
||||||
|
free(dict->name);
|
||||||
|
}
|
||||||
|
FREE(referencedTarget->dictionary.vector.data);
|
||||||
|
break;
|
||||||
|
case SaveClass:;
|
||||||
|
#ifndef WIN32
|
||||||
|
save_free_contexts(&referencedTarget->save->saveCtx);
|
||||||
|
f_close(&referencedTarget->save->saveFile);
|
||||||
|
FREE(referencedTarget->save);
|
||||||
|
#endif // !WIN32
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeVariable(Variable_t** target) {
|
||||||
|
// Add specific freeing logic here
|
||||||
|
Variable_t* referencedTarget = *target;
|
||||||
|
|
||||||
|
if (!referencedTarget->reference) {
|
||||||
|
freeVariableInternal(referencedTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FREE(referencedTarget);
|
||||||
|
*target = NULL;
|
||||||
|
}
|
||||||
25
source/script/genericClass.h
Normal file
25
source/script/genericClass.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "model.h"
|
||||||
|
|
||||||
|
Variable_t* copyVariableToPtr(Variable_t var);
|
||||||
|
|
||||||
|
#define VARARGCOUNT 255
|
||||||
|
|
||||||
|
#define ClassFunction(name) Variable_t* name(Variable_t* caller, Variable_t** args, u8 argsLen)
|
||||||
|
|
||||||
|
|
||||||
|
typedef Variable_t (*getMemberFunction)(Variable_t*, char*);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 classType;
|
||||||
|
getMemberFunction func;
|
||||||
|
} MemberGetters_t;
|
||||||
|
|
||||||
|
Variable_t getGenericFunctionMember(Variable_t* var, char* memberName, ClassFunctionTableEntry_t* entries, u8 len);
|
||||||
|
Variable_t* genericGet(Variable_t* var, CallArgs_t* ref);
|
||||||
|
Variable_t* genericCallDirect(Variable_t* var, Variable_t** args, u8 len);
|
||||||
|
Variable_t* callMemberFunctionDirect(Variable_t* var, char* memberName, Variable_t** args, u8 argsLen);
|
||||||
|
Variable_t* genericCall(Variable_t* var, CallArgs_t* ref);
|
||||||
|
void freeVariable(Variable_t** target);
|
||||||
|
Variable_t* callMemberFunction(Variable_t* var, char* memberName, CallArgs_t* args);
|
||||||
|
void freeVariableInternal(Variable_t* referencedTarget);
|
||||||
91
source/script/intClass.c
Normal file
91
source/script/intClass.c
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#include "intClass.h"
|
||||||
|
#include "StringClass.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <utils/sprintf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IntClass_t createIntClass(s64 in) {
|
||||||
|
IntClass_t a = { in };
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t newIntVariable(s64 x) {
|
||||||
|
// Integers are always read-only
|
||||||
|
Variable_t var = { .variableType = IntClass, .readOnly = 1, .integer = createIntClass(x) };
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(printIntVariable) {
|
||||||
|
IntClass_t* a = &caller->integer;
|
||||||
|
gfx_printf("%d", (int)a->value);
|
||||||
|
return &emptyClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFunction(intToStr) {
|
||||||
|
#ifndef WIN32
|
||||||
|
char buff[64] = { 0 };
|
||||||
|
s_printf(buff, "%d", getIntValue(caller));
|
||||||
|
return newStringVariablePtr(CpyStr(buff), 0, 1);
|
||||||
|
#else
|
||||||
|
return newIntVariablePtr(0);
|
||||||
|
#endif // !WIN32
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IntOpFunction(name, op) ClassFunction(name) { s64 i1 = getIntValue(caller); s64 i2 = getIntValue(*args); return newIntVariablePtr((i1 op i2)); }
|
||||||
|
|
||||||
|
IntOpFunction(addInt, +)
|
||||||
|
IntOpFunction(minusInt, -)
|
||||||
|
IntOpFunction(multInt, *)
|
||||||
|
IntOpFunction(divInt, /)
|
||||||
|
IntOpFunction(modInt, %)
|
||||||
|
IntOpFunction(smallerInt, <)
|
||||||
|
IntOpFunction(biggerInt, >)
|
||||||
|
IntOpFunction(smallerEqInt, <=)
|
||||||
|
IntOpFunction(biggerEqInt, >=)
|
||||||
|
IntOpFunction(eqInt, ==)
|
||||||
|
IntOpFunction(notEqInt, !=)
|
||||||
|
IntOpFunction(logicAndInt, &&)
|
||||||
|
IntOpFunction(logicOrInt, ||)
|
||||||
|
IntOpFunction(andInt, &)
|
||||||
|
IntOpFunction(orInt, |)
|
||||||
|
IntOpFunction(bitshiftLeftInt, <<)
|
||||||
|
IntOpFunction(bitshiftRightInt, >>)
|
||||||
|
|
||||||
|
ClassFunction(notInt) {
|
||||||
|
return newIntVariablePtr(!(getIntValue(caller)));
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 oneVarArgInt[] = { VARARGCOUNT };
|
||||||
|
u8 oneIntArgInt[] = { IntClass };
|
||||||
|
|
||||||
|
#define IntOpFunctionEntry(opName, functionName) {opName, functionName, 1, oneIntArgInt}
|
||||||
|
|
||||||
|
ClassFunctionTableEntry_t intFunctions[] = {
|
||||||
|
{"print", printIntVariable, 0, 0},
|
||||||
|
{"not", notInt, 0, 0},
|
||||||
|
{"str", intToStr, 0, 0},
|
||||||
|
IntOpFunctionEntry("+", addInt),
|
||||||
|
IntOpFunctionEntry("-", minusInt),
|
||||||
|
IntOpFunctionEntry("*", multInt),
|
||||||
|
IntOpFunctionEntry("/", divInt),
|
||||||
|
IntOpFunctionEntry("%", modInt),
|
||||||
|
IntOpFunctionEntry("<", smallerInt),
|
||||||
|
IntOpFunctionEntry(">", biggerInt),
|
||||||
|
IntOpFunctionEntry("<=", smallerEqInt),
|
||||||
|
IntOpFunctionEntry(">=", biggerEqInt),
|
||||||
|
IntOpFunctionEntry("==", eqInt),
|
||||||
|
IntOpFunctionEntry("!=", notEqInt),
|
||||||
|
IntOpFunctionEntry("&&", logicAndInt),
|
||||||
|
IntOpFunctionEntry("||", logicOrInt),
|
||||||
|
IntOpFunctionEntry("&", andInt),
|
||||||
|
IntOpFunctionEntry("|", orInt),
|
||||||
|
IntOpFunctionEntry("<<", bitshiftLeftInt),
|
||||||
|
IntOpFunctionEntry(">>", bitshiftRightInt),
|
||||||
|
};
|
||||||
|
|
||||||
|
Variable_t getIntegerMember(Variable_t* var, char* memberName) {
|
||||||
|
return getGenericFunctionMember(var, memberName, intFunctions, ARRAY_SIZE(intFunctions));
|
||||||
|
}
|
||||||
13
source/script/intClass.h
Normal file
13
source/script/intClass.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "model.h"
|
||||||
|
#include "genericClass.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define getIntValue(var) (var)->integer.value
|
||||||
|
|
||||||
|
IntClass_t createIntClass(s64 in);
|
||||||
|
|
||||||
|
Variable_t newIntVariable(s64 x);
|
||||||
|
#define newIntVariablePtr(x) copyVariableToPtr(newIntVariable(x))
|
||||||
|
Variable_t getIntegerMember(Variable_t* var, char* memberName);
|
||||||
@@ -1,308 +0,0 @@
|
|||||||
#include "lexer.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include "args.h"
|
|
||||||
#include <mem/heap.h>
|
|
||||||
|
|
||||||
static inline int isValidWord(char c) {
|
|
||||||
char r = c | 0x20;
|
|
||||||
return ((r >= 'a' && r <= 'z') || c == '_');
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isValidNum(char c) {
|
|
||||||
return (c >= '0' && c <= '9');
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isValidVar(char c) {
|
|
||||||
return (isValidWord(c) || isValidNum(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isValidHexNum(char c) {
|
|
||||||
char r = c | 0x20;
|
|
||||||
return (isValidNum(r) || (r >= 'a' && r <= 'f'));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define makeLexarToken(token, var) ((lexarToken_t) {token, var})
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u8 tokenC;
|
|
||||||
u8 tokenN;
|
|
||||||
} lexarTranslation_t;
|
|
||||||
|
|
||||||
lexarTranslation_t lexarTranslations[] = {
|
|
||||||
{'}', RCBracket},
|
|
||||||
{',', Seperator},
|
|
||||||
{'+', Plus},
|
|
||||||
{'-', Minus},
|
|
||||||
{'*', Multiply},
|
|
||||||
{'/', Division},
|
|
||||||
{'%', Mod},
|
|
||||||
{'!', Not},
|
|
||||||
{':', Selector},
|
|
||||||
{')', RBracket},
|
|
||||||
{']', RSBracket},
|
|
||||||
{'(', LBracket},
|
|
||||||
{'{', LCBracket},
|
|
||||||
{'=', Equal},
|
|
||||||
{'[', LSBracket},
|
|
||||||
{'<', Smaller},
|
|
||||||
{'>', Bigger},
|
|
||||||
{'\0', 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Should we make vars with next char being '(' a function and vars with an equals (or [x] wait how are we gonna spot that) after it to be an assignmentVar
|
|
||||||
*/
|
|
||||||
|
|
||||||
char lexarDebugGetTokenC(u8 tokenN) {
|
|
||||||
for (int i = 0; lexarTranslations[i].tokenC; i++) {
|
|
||||||
if (lexarTranslations[i].tokenN == tokenN) {
|
|
||||||
return lexarTranslations[i].tokenC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tokenN == EquationSeperator)
|
|
||||||
return ';';
|
|
||||||
|
|
||||||
return '?';
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* !! we need to remake this
|
|
||||||
void lexarVectorClear(lexarVector_t* vec) {
|
|
||||||
for (int i = 0; i < vec->stored; i++) {
|
|
||||||
if (vec->tokens[i].token == Variable || vec->tokens[i].token == StrLit)
|
|
||||||
if (vec->tokens[i].text != NULL)
|
|
||||||
free(vec->tokens[i].text);
|
|
||||||
}
|
|
||||||
free(vec->tokens);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void lexarVectorClear(Vector_t *v){
|
|
||||||
vecPDefArray(lexarToken_t*, entries, v);
|
|
||||||
|
|
||||||
for (int i = 0; i < v->count; i++){
|
|
||||||
if (entries[i].token != IntLit && entries[i].text != NULL){
|
|
||||||
free(entries[i].text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vecFreePtr(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ELIFC(c) else if (*in == c)
|
|
||||||
|
|
||||||
Vector_t runLexer(const char* in, u32 len) {
|
|
||||||
const char *start = in;
|
|
||||||
Vector_t vec = newVec(sizeof(lexarToken_t), 16);
|
|
||||||
// store last var for re-assignment
|
|
||||||
// var -> func if next obj is '('
|
|
||||||
// var -> assignment if next obj is '='
|
|
||||||
// var -> arrassignment if next obj is '[' and before '=' is ']'
|
|
||||||
// maybe measure len between ( ) and [ ], so this doesn't have to be done during runtime?
|
|
||||||
// We also have to support (()). maybe if '(' set indent level, then if ')' minus indent level, set len. indent level contains {u8 level, u16 token, u16 startoffset}
|
|
||||||
|
|
||||||
u32 lastAssignment = 0;
|
|
||||||
|
|
||||||
while ((in - start) < len) {
|
|
||||||
lexarToken_t* lx = vecGetArray(lexarToken_t*, vec);
|
|
||||||
|
|
||||||
if ((lx[vec.count - 2].token == StrLit || lx[vec.count - 2].token == IntLit || lx[vec.count - 2].token == Variable || lx[vec.count - 2].token == RSBracket || lx[vec.count - 2].token == RBracket)
|
|
||||||
&& (lx[vec.count - 1].token == Variable || lx[vec.count - 1].token == LCBracket || lx[vec.count - 1].token == RCBracket)) {
|
|
||||||
if (!(lx[lastAssignment].token == ArrayVariableAssignment && lx[vec.count - 1].token == Variable && lx[vec.count - 2].token == RSBracket)) {
|
|
||||||
lexarToken_t holder = lx[vec.count - 1];
|
|
||||||
lx[vec.count - 1] = makeLexarToken(EquationSeperator, 0);
|
|
||||||
vecAddElement(&vec, holder);
|
|
||||||
lx = vecGetArray(lexarToken_t*, vec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isValidWord(*in)) {
|
|
||||||
char* startWord = in;
|
|
||||||
in++;
|
|
||||||
while (isValidVar(*in))
|
|
||||||
in++;
|
|
||||||
|
|
||||||
vecAddElement(&vec, (makeLexarToken(Variable, utils_copyStringSize(startWord, in - startWord))));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (isValidNum(*in) || (*in == '-' && isValidNum(in[1]))) {
|
|
||||||
int parse = 0;
|
|
||||||
u8 negative = (*in == '-');
|
|
||||||
if (negative)
|
|
||||||
in++;
|
|
||||||
|
|
||||||
if (*in == '0' && (in[1] | 0x20) == 'x') {
|
|
||||||
in += 2;
|
|
||||||
while (isValidHexNum(*in)) {
|
|
||||||
parse = parse * 16 + (*in & 0x0F) + (*in >= 'A' ? 9 : 0);
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else while (isValidNum(*in)) {
|
|
||||||
parse = parse * 10 + *in++ - '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negative)
|
|
||||||
parse *= -1;
|
|
||||||
|
|
||||||
vecAddElement(&vec, makeLexarToken(IntLit, parse));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ELIFC('(') {
|
|
||||||
if (lx[vec.count - 1].token == Variable)
|
|
||||||
lx[vec.count - 1].token = Function;
|
|
||||||
|
|
||||||
vecAddElement(&vec, makeLexarToken(LBracket, 0));
|
|
||||||
}
|
|
||||||
ELIFC('[') {
|
|
||||||
if (lx[vec.count - 1].token == Variable)
|
|
||||||
lx[vec.count - 1].token = ArrayVariable;
|
|
||||||
|
|
||||||
vecAddElement(&vec, makeLexarToken(LSBracket, 0));
|
|
||||||
}
|
|
||||||
ELIFC('=') { // Do we need to keep = if the vars are assignments anyway?
|
|
||||||
if (in[1] == '='){
|
|
||||||
vecAddElement(&vec, makeLexarToken(EqualEqual, 0));
|
|
||||||
in++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lx[vec.count - 1].token == Variable)
|
|
||||||
lx[vec.count - 1].token = VariableAssignment;
|
|
||||||
|
|
||||||
else if (lx[vec.count - 1].token == RSBracket) {
|
|
||||||
int back = 1;
|
|
||||||
while (lx[vec.count - back].token != ArrayVariable) {
|
|
||||||
back++;
|
|
||||||
if (vec.count - back < 0)
|
|
||||||
break; // major error
|
|
||||||
}
|
|
||||||
if (lx[vec.count - back].token == ArrayVariable) {
|
|
||||||
lx[vec.count - back].token = ArrayVariableAssignment;
|
|
||||||
lastAssignment = vec.count - back;
|
|
||||||
in++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastAssignment = 0;
|
|
||||||
}
|
|
||||||
ELIFC('{') {
|
|
||||||
if (lx[vec.count - 1].token == VariableAssignment) {
|
|
||||||
lx[vec.count - 1].token = FunctionAssignment;
|
|
||||||
}
|
|
||||||
vecAddElement(&vec, makeLexarToken(LCBracket, 0));
|
|
||||||
}
|
|
||||||
ELIFC('"') {
|
|
||||||
char* startStr = ++in;
|
|
||||||
int len = 0;
|
|
||||||
while (*in != '"') {
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
len = in - startStr;
|
|
||||||
|
|
||||||
char* storage = malloc(len + 1);
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
if (startStr[i] == '\\') {
|
|
||||||
if (startStr[i + 1] == 'n') {
|
|
||||||
storage[pos++] = '\n';
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startStr[i + 1] == 'r') {
|
|
||||||
storage[pos++] = '\r';
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storage[pos++] = startStr[i];
|
|
||||||
}
|
|
||||||
storage[pos] = '\0';
|
|
||||||
|
|
||||||
vecAddElement(&vec, makeLexarToken(StrLit, storage));
|
|
||||||
}
|
|
||||||
ELIFC('#') {
|
|
||||||
while (*in != '\n')
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
ELIFC('&') {
|
|
||||||
if (in[1] == '&') {
|
|
||||||
vecAddElement(&vec, makeLexarToken(LogicAND, 0));
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vecAddElement(&vec, makeLexarToken(AND, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ELIFC('|') {
|
|
||||||
if (in[1] == '|') {
|
|
||||||
vecAddElement(&vec, makeLexarToken(LogicOR, 0));
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vecAddElement(&vec, makeLexarToken(OR, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ELIFC('>'){
|
|
||||||
if (in[1] == '>'){
|
|
||||||
vecAddElement(&vec, makeLexarToken(BitShiftRight, 0));
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int a = (in[1] == '=') ? 1 : 0;
|
|
||||||
vecAddElement(&vec, makeLexarToken(Bigger, 0));
|
|
||||||
in += a;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
ELIFC('<'){
|
|
||||||
if (in[1] == '<'){
|
|
||||||
vecAddElement(&vec, makeLexarToken(BitShiftLeft, 0));
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int a = (in[1] == '=') ? 1 : 0;
|
|
||||||
vecAddElement(&vec, makeLexarToken(Smaller + a, 0));
|
|
||||||
in += a;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int val = 0;
|
|
||||||
|
|
||||||
for (int i = 0; lexarTranslations[i].tokenC; i++) {
|
|
||||||
if (lexarTranslations[i].tokenC == *in) {
|
|
||||||
val = lexarTranslations[i].tokenN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
in++;
|
|
||||||
|
|
||||||
if (*in == '=' && val >= Smaller && val <= Not) {
|
|
||||||
val++;
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (val != Invalid)
|
|
||||||
vecAddElement(&vec, makeLexarToken(val, 0));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexarToken_t* lx = vecGetArray(lexarToken_t*, vec);
|
|
||||||
if ((lx[vec.count - 2].token == StrLit || lx[vec.count - 2].token == IntLit || lx[vec.count - 2].token == Variable || lx[vec.count - 2].token == RSBracket || lx[vec.count - 2].token == RBracket)
|
|
||||||
&& (lx[vec.count - 1].token == Variable || lx[vec.count - 1].token == LCBracket || lx[vec.count - 1].token == RCBracket)) {
|
|
||||||
lexarToken_t holder = lx[vec.count - 1];
|
|
||||||
lx[vec.count - 1] = makeLexarToken(EquationSeperator, 0);
|
|
||||||
vecAddElement(&vec, holder);
|
|
||||||
}
|
|
||||||
|
|
||||||
vecAddElement(&vec, makeLexarToken(EquationSeperator, 0));
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
Vector_t runLexer(const char* in, u32 len);
|
|
||||||
char lexarDebugGetTokenC(u8 tokenN);
|
|
||||||
void lexarVectorClear(Vector_t *v);
|
|
||||||
43
source/script/model.c
Normal file
43
source/script/model.c
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include "model.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "StringClass.h"
|
||||||
|
#include "intClass.h"
|
||||||
|
|
||||||
|
TokenConvertion_t tokenConvertions[] = {
|
||||||
|
{SmallerEqual, "<="},
|
||||||
|
{BiggerEqual, ">="},
|
||||||
|
{NotEqual, "!="},
|
||||||
|
{LogicAnd, "&&"},
|
||||||
|
{LogicOr, "||"},
|
||||||
|
{EqualEqual, "=="},
|
||||||
|
|
||||||
|
{BitShiftLeft, "<<"},
|
||||||
|
{BitShiftRight, ">>"},
|
||||||
|
|
||||||
|
{Not, "!"},
|
||||||
|
{Plus, "+"},
|
||||||
|
{Equals, "="},
|
||||||
|
{Minus, "-"},
|
||||||
|
{Multiply, "*"},
|
||||||
|
{Division, "/"},
|
||||||
|
{Modulo, "%"},
|
||||||
|
|
||||||
|
{LeftSquareBracket, "["},
|
||||||
|
{LeftCurlyBracket, "{"},
|
||||||
|
{LeftBracket, "("},
|
||||||
|
{RightSquareBracket, "]"},
|
||||||
|
{RightCurlyBracket, "}"},
|
||||||
|
{RightBracket, ")"},
|
||||||
|
|
||||||
|
{Smaller, "<"},
|
||||||
|
{Bigger, ">"},
|
||||||
|
|
||||||
|
{And, "&"},
|
||||||
|
{Or, "|"},
|
||||||
|
{Dot, "."},
|
||||||
|
{EquationSeperator, ","},
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 tokenConvertionCount = ARRAY_SIZE(tokenConvertions);
|
||||||
|
|
||||||
|
Variable_t emptyClass = { .variableType = EmptyClass, .readOnly = 1, .reference = 1, .gcDoNotFree = 1 };
|
||||||
276
source/script/model.h
Normal file
276
source/script/model.h
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned int u32;
|
||||||
|
typedef long long s64;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma pack(1)
|
||||||
|
typedef struct {
|
||||||
|
void* data;
|
||||||
|
u32 capacity;
|
||||||
|
u32 count;
|
||||||
|
u8 elemSz;
|
||||||
|
} Vector_t;
|
||||||
|
#else
|
||||||
|
#include "../utils/vector.h"
|
||||||
|
#include <libs/nx_savedata/save.h>
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
None = 0,
|
||||||
|
IntClass,
|
||||||
|
FunctionClass,
|
||||||
|
StringClass,
|
||||||
|
ByteArrayClass,
|
||||||
|
StringArrayClass,
|
||||||
|
IntArrayClass,
|
||||||
|
UnresolvedArrayClass,
|
||||||
|
DictionaryClass,
|
||||||
|
EmptyClass,
|
||||||
|
SolvedArrayReferenceClass,
|
||||||
|
SaveClass,
|
||||||
|
ElseClass,
|
||||||
|
ReferenceType,
|
||||||
|
} VariableType_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Invalid = 0,
|
||||||
|
Variable,
|
||||||
|
BetweenBrackets,
|
||||||
|
Not,
|
||||||
|
|
||||||
|
Plus,
|
||||||
|
Equals,
|
||||||
|
Minus,
|
||||||
|
Multiply,
|
||||||
|
Division,
|
||||||
|
Modulo,
|
||||||
|
|
||||||
|
LeftSquareBracket,
|
||||||
|
LeftCurlyBracket,
|
||||||
|
LeftBracket,
|
||||||
|
RightSquareBracket,
|
||||||
|
RightCurlyBracket,
|
||||||
|
RightBracket,
|
||||||
|
|
||||||
|
Smaller,
|
||||||
|
SmallerEqual,
|
||||||
|
Bigger,
|
||||||
|
BiggerEqual,
|
||||||
|
EqualEqual,
|
||||||
|
NotEqual,
|
||||||
|
LogicAnd,
|
||||||
|
LogicOr,
|
||||||
|
|
||||||
|
BitShiftLeft,
|
||||||
|
BitShiftRight,
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
|
||||||
|
EquationSeperator,
|
||||||
|
Dot,
|
||||||
|
CallArgs,
|
||||||
|
} Token_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ActionGet = 0,
|
||||||
|
ActionSet,
|
||||||
|
ActionCall,
|
||||||
|
} ActionType_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ActionExtraNone = 0,
|
||||||
|
ActionExtraArrayIndex,
|
||||||
|
ActionExtraMemberName,
|
||||||
|
ActionExtraCallArgs,
|
||||||
|
ActionExtraCallArgsFunction
|
||||||
|
} ActionExtraType_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Change to a Vector_t with Operator_t's
|
||||||
|
typedef struct {
|
||||||
|
Vector_t operations; // Operation_t. Equations seperated by EquationSep
|
||||||
|
} Function_t;
|
||||||
|
|
||||||
|
struct _ClassFunctionTableEntry_t;
|
||||||
|
struct _Variable_t;
|
||||||
|
|
||||||
|
typedef struct _FunctionClass_t {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u8 builtIn : 1;
|
||||||
|
u8 firstArgAsFunction : 1;
|
||||||
|
};
|
||||||
|
u8 unionFunctionOptions;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
Function_t function;
|
||||||
|
struct {
|
||||||
|
struct _ClassFunctionTableEntry_t* builtInPtr;
|
||||||
|
struct _Variable_t* origin;
|
||||||
|
u8 len;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} FunctionClass_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ArrayType_Int = 0,
|
||||||
|
ArrayType_String,
|
||||||
|
ArrayType_Byte
|
||||||
|
} ArrayType_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
Vector_t vector; // vector of typeof(value)
|
||||||
|
struct {
|
||||||
|
struct _Variable_t* arrayClassReference;
|
||||||
|
u32 offset;
|
||||||
|
u32 len;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} ArrayClass_t;
|
||||||
|
|
||||||
|
typedef struct _UnsolvedArrayClass_t {
|
||||||
|
Vector_t operations; // Operator_t
|
||||||
|
} UnsolvedArrayClass_t;
|
||||||
|
|
||||||
|
typedef struct _DictionaryClass_t {
|
||||||
|
Vector_t vector; // vector of typeof(Dict_t)
|
||||||
|
} DictionaryClass_t;
|
||||||
|
|
||||||
|
typedef struct _IntClass_t {
|
||||||
|
s64 value;
|
||||||
|
} IntClass_t;
|
||||||
|
|
||||||
|
typedef struct _StringClass_t {
|
||||||
|
char* value;
|
||||||
|
struct {
|
||||||
|
u8 free : 1;
|
||||||
|
};
|
||||||
|
} StringClass_t;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
typedef struct {
|
||||||
|
save_ctx_t saveCtx;
|
||||||
|
FIL saveFile;
|
||||||
|
} SaveClass_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _Variable_t {
|
||||||
|
//void* variable;
|
||||||
|
union {
|
||||||
|
FunctionClass_t function;
|
||||||
|
UnsolvedArrayClass_t unsolvedArray;
|
||||||
|
DictionaryClass_t dictionary;
|
||||||
|
IntClass_t integer;
|
||||||
|
StringClass_t string;
|
||||||
|
ArrayClass_t solvedArray;
|
||||||
|
#ifndef WIN32
|
||||||
|
SaveClass_t *save;
|
||||||
|
#endif
|
||||||
|
struct _Variable_t* referenceType;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u8 variableType : 5;
|
||||||
|
u8 readOnly : 1;
|
||||||
|
u8 reference : 1;
|
||||||
|
u8 gcDoNotFree : 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
u8 tagCount;
|
||||||
|
} Variable_t;
|
||||||
|
|
||||||
|
typedef struct _CallArgs_t {
|
||||||
|
struct {
|
||||||
|
u8 action : 4;
|
||||||
|
u8 extraAction : 4;
|
||||||
|
};
|
||||||
|
void* extra; // Function_t for arrayIdx, char* for member, Function_t for funcCall, Function_t x2 for funcCallArgs
|
||||||
|
struct _CallArgs_t* next;
|
||||||
|
} CallArgs_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* data;
|
||||||
|
u32 len;
|
||||||
|
} Array_t;
|
||||||
|
|
||||||
|
typedef Variable_t* (*ClassFunction)(Variable_t* caller, Variable_t** args, u8 argsLen);
|
||||||
|
|
||||||
|
typedef struct _ClassFunctionTableEntry_t {
|
||||||
|
char* name;
|
||||||
|
ClassFunction func;
|
||||||
|
u8 argCount;
|
||||||
|
u8* argTypes;
|
||||||
|
} ClassFunctionTableEntry_t;
|
||||||
|
|
||||||
|
typedef struct _VariableReference_t {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u8 staticVariableSet : 1;
|
||||||
|
u8 staticVariableRef : 1;
|
||||||
|
u8 staticVariableType : 2; // 0 = ref, 1 = int, 2 = str, 3 = stdlib func
|
||||||
|
};
|
||||||
|
u8 staticVariableOptionsUnion;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
Variable_t* staticVariable;
|
||||||
|
char* name;
|
||||||
|
Array_t betweenBrackets;
|
||||||
|
s64 integerType;
|
||||||
|
char* stringType;
|
||||||
|
struct {
|
||||||
|
ClassFunctionTableEntry_t* staticFunction;
|
||||||
|
u8 staticFunctionLen;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} VariableReference_t;
|
||||||
|
|
||||||
|
//typedef Variable_t* (*classFunctionTable)(VariableReference_t*);
|
||||||
|
|
||||||
|
typedef Variable_t* (*classFunctionTable)(char*, Variable_t*, VariableReference_t*, Vector_t*);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* name;
|
||||||
|
Variable_t* var;
|
||||||
|
} Dict_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 token : 8;
|
||||||
|
char strToken[3];
|
||||||
|
} TokenConvertion_t;
|
||||||
|
|
||||||
|
extern TokenConvertion_t tokenConvertions[];
|
||||||
|
extern u32 tokenConvertionCount;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Vector_t operations; // Operator_t
|
||||||
|
} Equation_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct {
|
||||||
|
u8 token : 7;
|
||||||
|
u8 not : 1;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
VariableReference_t variable;
|
||||||
|
CallArgs_t callArgs;
|
||||||
|
char* tokenStr;
|
||||||
|
s64 lineNumber;
|
||||||
|
};
|
||||||
|
// probably should add u16 lineNum here
|
||||||
|
} Operator_t;
|
||||||
|
|
||||||
|
extern Variable_t emptyClass;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
@@ -1,130 +1,670 @@
|
|||||||
#include "args.h"
|
#include "model.h"
|
||||||
#include "types.h"
|
#include "compat.h"
|
||||||
#include "variables.h"
|
#include "compat.h"
|
||||||
#include "lexer.h"
|
#include "parser.h"
|
||||||
#include "../gfx/gfx.h"
|
#include <stdlib.h>
|
||||||
#include "../utils/utils.h"
|
#include <string.h>
|
||||||
#include <mem/heap.h>
|
|
||||||
#include "../hid/hid.h"
|
|
||||||
|
|
||||||
#define scriptResultCreate(resCode, nearToken) (scriptResult_t) {resCode, nearToken, 1}
|
#include "intClass.h"
|
||||||
#define scriptResultCreateLen(resCode, nearToken, len) (scriptResult_t) {resCode, nearToken, len}
|
#include "StringClass.h"
|
||||||
|
#include "unsolvedArrayClass.h"
|
||||||
|
#include "functionClass.h"
|
||||||
|
|
||||||
scriptResult_t runFunction(scriptCtx_t* ctx, u32 len) {
|
#include "scriptError.h"
|
||||||
lexarToken_t* tokens = vecGetArray(lexarToken_t*, ctx->script);
|
#include "standardLibrary.h"
|
||||||
Variable_t res = solveEquation(ctx, &tokens[ctx->startEquation], len, 1);
|
|
||||||
|
|
||||||
if (res.varType == ErrType) {
|
#ifndef WIN32
|
||||||
return scriptResultCreateLen(res.integerType, &tokens[ctx->startEquation], len);
|
#include "../tegraexplorer/tconf.h"
|
||||||
|
#include <storage/nx_sd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int isValidWord(char c) {
|
||||||
|
char r = c | 0x20;
|
||||||
|
return ((r >= 'a' && r <= 'z') || c == '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isValidNum(char c) {
|
||||||
|
return (c >= '0' && c <= '9');
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isValidVar(char c) {
|
||||||
|
return (isValidWord(c) || isValidNum(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isValidHexNum(char c) {
|
||||||
|
char r = c | 0x20;
|
||||||
|
return (isValidNum(r) || (r >= 'a' && r <= 'f'));
|
||||||
|
}
|
||||||
|
|
||||||
|
char* getTokenText(u8 token) {
|
||||||
|
for (u32 i = 0; i < tokenConvertionCount; i++) {
|
||||||
|
if (tokenConvertions[i].token == token)
|
||||||
|
return tokenConvertions[i].strToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
return scriptResultCreate(0, 0);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RUNFUNCWITHPANIC(ctx, len) scriptResult_t res = runFunction(ctx, len); if (res.resCode != 0) return res
|
char* utils_copyStringSize(const char* in, int size) {
|
||||||
|
if (size > strlen(in) || size < 0)
|
||||||
|
size = strlen(in);
|
||||||
|
|
||||||
static inline int checkIfVar(u8 token) {
|
char* out = calloc(size + 1, 1);
|
||||||
return (token == StrLit || token == IntLit || token == Variable || token == RSBracket || token == ArrayVariable);
|
//strncpy(out, in, size);
|
||||||
|
if (size)
|
||||||
|
memcpy(out, in, size);
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptResult_t mainLoop(scriptCtx_t* ctx) {
|
#define ELIFC(c) else if (*in == c)
|
||||||
ctx->startEquation = 0;
|
|
||||||
lexarToken_t* lexArr = vecGetArray(lexarToken_t*, ctx->script);
|
|
||||||
for (ctx->curPos = 0; ctx->curPos < ctx->script.count; ctx->curPos++) {
|
|
||||||
u32 i = ctx->curPos;
|
|
||||||
lexarToken_t curToken = lexArr[i];
|
|
||||||
|
|
||||||
if (curToken.token == EquationSeperator) {
|
Vector_t script;
|
||||||
RUNFUNCWITHPANIC(ctx, ctx->curPos - ctx->startEquation);
|
s64 lineNumber;
|
||||||
ctx->startEquation = ctx->curPos + 1;
|
|
||||||
}
|
|
||||||
else if (curToken.token == FunctionAssignment) {
|
|
||||||
setCurIndentInstruction(ctx, 1, 0, -1);
|
|
||||||
dict_t x = newDict(CpyStr(curToken.text), newVar(JumpType, 0, .integerType = ctx->curPos + 1));
|
|
||||||
vecAddElement(&ctx->varDict, x);
|
|
||||||
}
|
|
||||||
else if (curToken.token == LCBracket) {
|
|
||||||
indentInstructor_t* ins = getCurIndentInstruction(ctx);
|
|
||||||
if (ins->active) {
|
|
||||||
if (ins->skip) {
|
|
||||||
int distance = distanceBetweenTokens(&lexArr[i + 1], ctx->script.count - i - 1, LCBracket, RCBracket);
|
|
||||||
if (distance < 0)
|
|
||||||
return scriptResultCreate(ERRSYNTAX, &lexArr[i]);
|
|
||||||
ctx->curPos += distance + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ctx->indentIndex++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return scriptResultCreate(ERRINACTIVEINDENT, &lexArr[i]);
|
|
||||||
|
|
||||||
ctx->startEquation = ctx->curPos + 1;
|
enum TokenType {
|
||||||
}
|
Token_Variable = 0,
|
||||||
else if (curToken.token == RCBracket) {
|
Token_String,
|
||||||
ctx->indentIndex--;
|
Token_Int,
|
||||||
indentInstructor_t* ins = getCurIndentInstruction(ctx);
|
Token_Token,
|
||||||
if (ins->active && ins->jump) {
|
Token_Err,
|
||||||
ctx->curPos = ins->jumpLoc - 1;
|
Token_Fatal_Err,
|
||||||
}
|
|
||||||
|
|
||||||
ins->active = 0;
|
|
||||||
ctx->startEquation = ctx->curPos + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return scriptResultCreate(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void printToken(lexarToken_t* token) {
|
|
||||||
switch (token->token) {
|
|
||||||
case Variable:
|
|
||||||
case ArrayVariable:
|
|
||||||
case Function:
|
|
||||||
gfx_printf("%s", token->text);
|
|
||||||
break;
|
|
||||||
case FunctionAssignment:
|
|
||||||
case VariableAssignment:
|
|
||||||
case ArrayVariableAssignment:
|
|
||||||
gfx_printf("%s=", token->text);
|
|
||||||
break;
|
|
||||||
case StrLit:
|
|
||||||
//printf("%d: '%s'\n", vec.tokens[i].token, vec.tokens[i].text);
|
|
||||||
gfx_printf("\"%s\"", token->text);
|
|
||||||
break;
|
|
||||||
case IntLit:
|
|
||||||
//printf("%d: %d\n", vec.tokens[i].token, vec.tokens[i].val);
|
|
||||||
gfx_printf("%d", token->val);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//printf("%d: %c\n", vec.tokens[i].token, lexarDebugGetTokenC(vec.tokens[i].token));
|
|
||||||
gfx_printf("%c", lexarDebugGetTokenC(token->token));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *ErrorText[] = {
|
|
||||||
"Bad operator",
|
|
||||||
"Double not",
|
|
||||||
"Syntax err",
|
|
||||||
"Invalid type",
|
|
||||||
"No var",
|
|
||||||
"No func",
|
|
||||||
"Inactive indent",
|
|
||||||
"Div by 0",
|
|
||||||
"Func fail"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void printError(scriptResult_t res) {
|
typedef enum {
|
||||||
if (res.resCode) {
|
History_Function = 0,
|
||||||
if (res.resCode == ERRESCSCRIPT)
|
History_Bracket,
|
||||||
return;
|
History_Array,
|
||||||
|
} StackHistory_t;
|
||||||
|
|
||||||
gfx_printf("Error found! %s\nNear: ", ErrorText[res.resCode - 1]);
|
char* end;
|
||||||
for (int i = 0; i < res.len; i++) {
|
|
||||||
printToken(&res.nearToken[i]);
|
u8 nextToken(char** inPtr, void** val) {
|
||||||
|
char* in = *inPtr;
|
||||||
|
u8 ret = Token_Err;
|
||||||
|
while (ret == Token_Err) {
|
||||||
|
if (*in == '#') {
|
||||||
|
if (!memcmp(in + 1, "REQUIRE ", 8)) {
|
||||||
|
if (!memcmp(in + 9, "VER ", 4)) {
|
||||||
|
char* verStart = in + 13;
|
||||||
|
char* verEnd = verStart;
|
||||||
|
|
||||||
|
while (isValidNum(*verEnd) || *verEnd == '.')
|
||||||
|
verEnd++;
|
||||||
|
|
||||||
|
u8 outdated = (verEnd - verStart != strlen(LP_VER));
|
||||||
|
|
||||||
|
if (!outdated){
|
||||||
|
outdated = (memcmp(LP_VER, verStart, verEnd - verStart) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outdated) {
|
||||||
|
printScriptError(SCRIPT_LEXER_FATAL, "Script requires a newer TegraExplorer version!");
|
||||||
|
return Token_Fatal_Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!memcmp(in + 9, "MINERVA", 7)) {
|
||||||
|
#ifdef WIN32
|
||||||
|
u8 minervaEnabled = 0;
|
||||||
|
#else
|
||||||
|
u8 minervaEnabled = TConf.minervaEnabled;
|
||||||
|
#endif
|
||||||
|
if (!minervaEnabled) {
|
||||||
|
printScriptError(SCRIPT_LEXER_FATAL, "Extended memory required.\nPut the bootloader folder from hekate on your sd!");
|
||||||
|
return Token_Fatal_Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!memcmp(in + 9, "KEYS", 4)) {
|
||||||
|
#ifdef WIN32
|
||||||
|
u8 gotKeys = 0;
|
||||||
|
#else
|
||||||
|
u8 gotKeys = TConf.keysDumped;
|
||||||
|
#endif
|
||||||
|
if (!gotKeys){
|
||||||
|
printScriptError(SCRIPT_LEXER_FATAL, "Keys required.\nMake sure you're on the latest version of TegraExplorer!");
|
||||||
|
return Token_Fatal_Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!memcmp(in + 9, "SD", 2)) {
|
||||||
|
#ifdef WIN32
|
||||||
|
u8 gotSd = 0;
|
||||||
|
#else
|
||||||
|
u8 gotSd = sd_mount();
|
||||||
|
#endif
|
||||||
|
if (!gotSd){
|
||||||
|
printScriptError(SCRIPT_LEXER_FATAL, "Sd required.");
|
||||||
|
return Token_Fatal_Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*in && *in != '\n')
|
||||||
|
in++;
|
||||||
|
|
||||||
|
lineNumber++;
|
||||||
|
scriptCurrentLine = lineNumber;
|
||||||
}
|
}
|
||||||
|
else if (isValidWord(*in)) {
|
||||||
|
char* startWord = in;
|
||||||
|
in++;
|
||||||
|
while (isValidVar(*in))
|
||||||
|
in++;
|
||||||
|
|
||||||
gfx_printf("\nPress any key to exit");
|
char* str = utils_copyStringSize(startWord, in - startWord);
|
||||||
hidWait();
|
|
||||||
|
//gfx_printf("Variable: '%s'\n", str);
|
||||||
|
ret = Token_Variable;
|
||||||
|
*val = str;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (isValidNum(*in) || (*in == '-' && isValidNum(in[1]))) {
|
||||||
|
s64 parse = 0;
|
||||||
|
u8 negative = (*in == '-');
|
||||||
|
if (negative)
|
||||||
|
in++;
|
||||||
|
|
||||||
|
if (*in == '0' && (in[1] | 0x20) == 'x') {
|
||||||
|
in += 2;
|
||||||
|
while (isValidHexNum(*in)) {
|
||||||
|
parse = parse * 16 + (*in & 0x0F) + (*in >= 'A' ? 9 : 0);
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else while (isValidNum(*in)) {
|
||||||
|
parse = parse * 10 + *in++ - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (negative)
|
||||||
|
parse *= -1;
|
||||||
|
|
||||||
|
//gfx_printf("Integer: '%d'\n", parse);
|
||||||
|
ret = Token_Int;
|
||||||
|
|
||||||
|
s64* parsePersistent = malloc(sizeof(s64));
|
||||||
|
*parsePersistent = parse;
|
||||||
|
|
||||||
|
*val = parsePersistent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ELIFC('"') {
|
||||||
|
char* startStr = ++in;
|
||||||
|
int len = 0;
|
||||||
|
while (*in != '"') {
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
len = in - startStr;
|
||||||
|
|
||||||
|
char* storage = malloc(len + 1);
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (startStr[i] == '\\') {
|
||||||
|
if (startStr[i + 1] == 'n') {
|
||||||
|
storage[pos++] = '\n';
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startStr[i + 1] == 'r') {
|
||||||
|
storage[pos++] = '\r';
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
storage[pos++] = startStr[i];
|
||||||
|
}
|
||||||
|
storage[pos] = '\0';
|
||||||
|
|
||||||
|
//gfx_printf("String: '%s'\n", storage);
|
||||||
|
ret = Token_String;
|
||||||
|
*val = storage;
|
||||||
|
}
|
||||||
|
else if (*in == '\0' || in > end) {
|
||||||
|
*inPtr = in;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else if (*in == '\n'){
|
||||||
|
lineNumber++;
|
||||||
|
scriptCurrentLine = lineNumber;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (u32 i = 0; i < tokenConvertionCount; i++) {
|
||||||
|
TokenConvertion_t t = tokenConvertions[i];
|
||||||
|
if (!memcmp(t.strToken, in, (t.strToken[1] == '\0') ? 1 : 2)) {
|
||||||
|
//gfx_printf("Token: '%s'\n", t.strToken);
|
||||||
|
ret = Token_Token;
|
||||||
|
*val = t.token;
|
||||||
|
|
||||||
|
if (t.strToken[1] != '\0')
|
||||||
|
in++;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*inPtr = in;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CreateVariableReferenceStatic(var) VariableReference_t reference = { .staticVariable = var, .staticVariableSet = 1, .staticVariableRef = 1 }
|
||||||
|
#define CreateVariableReferenceStr(str) VariableReference_t reference = { .name = str }
|
||||||
|
|
||||||
|
void setNextActionOperator(Vector_t *opHolder, ActionType_t action, ActionExtraType_t actionExtra, void *extra) {
|
||||||
|
Operator_t* ops = opHolder->data;
|
||||||
|
Operator_t* lastOp = &ops[opHolder->count - 1];
|
||||||
|
|
||||||
|
if (lastOp->token == CallArgs) {
|
||||||
|
CallArgs_t* last = &lastOp->callArgs;
|
||||||
|
for (; last->next != NULL; last = last->next);
|
||||||
|
last->next = calloc(sizeof(CallArgs_t), 1);
|
||||||
|
last->next->action = action;
|
||||||
|
last->next->extra = extra;
|
||||||
|
last->next->extraAction = actionExtra;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Operator_t newOp = { .token = CallArgs };
|
||||||
|
newOp.callArgs.action = action;
|
||||||
|
newOp.callArgs.extra = extra;
|
||||||
|
newOp.callArgs.extraAction = actionExtra;
|
||||||
|
vecAdd(opHolder, newOp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CallArgs_t* getLastRef(CallArgs_t* ref) {
|
||||||
|
for (; ref->next != NULL; ref = ref->next);
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
int isLastVarSet(Operator_t* opHolder) {
|
||||||
|
return (opHolder->token == CallArgs && getLastRef(&opHolder->callArgs)->action == ActionSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
int isLastVarCall(Operator_t* opHolder) {
|
||||||
|
return (opHolder->token == CallArgs && getLastRef(&opHolder->callArgs)->action == ActionCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParserRet_t parseScript(char* in, u32 len) {
|
||||||
|
Vector_t functionStack; // Function_t
|
||||||
|
Vector_t stackHistoryHolder; // StaticHistory_t
|
||||||
|
Vector_t staticVariableHolder; // Variable_t
|
||||||
|
|
||||||
|
functionStack = newVec(sizeof(Function_t), 0);
|
||||||
|
Function_t firstFunction = createEmptyFunction();
|
||||||
|
vecAdd(&functionStack, firstFunction);
|
||||||
|
|
||||||
|
staticVariableHolder = newVec(sizeof(Variable_t), 0);
|
||||||
|
|
||||||
|
stackHistoryHolder = newVec(sizeof(StackHistory_t), 1);
|
||||||
|
StackHistory_t firstHistory = History_Function;
|
||||||
|
vecAdd(&stackHistoryHolder, firstHistory);
|
||||||
|
u8 notNext = 0;
|
||||||
|
lineNumber = 1;
|
||||||
|
scriptCurrentLine = 1;
|
||||||
|
end = in + len;
|
||||||
|
|
||||||
|
while (*in && in <= end) {
|
||||||
|
Function_t* lastFunc = getStackEntry(&functionStack);
|
||||||
|
StackHistory_t* lastHistory = getStackEntry(&stackHistoryHolder);
|
||||||
|
|
||||||
|
Operator_t* lastOp = NULL;
|
||||||
|
|
||||||
|
if (lastFunc) {
|
||||||
|
lastOp = getStackEntry(&lastFunc->operations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* var = NULL;
|
||||||
|
u8 tokenType = nextToken(&in, &var);
|
||||||
|
|
||||||
|
if (tokenType == Token_Err)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (tokenType == Token_Fatal_Err)
|
||||||
|
return (ParserRet_t) { 0 };
|
||||||
|
|
||||||
|
Operator_t op = { .token = Variable };
|
||||||
|
|
||||||
|
if (tokenType >= Token_Variable && tokenType <= Token_Int && lastOp) {
|
||||||
|
if (lastOp->token == Variable || lastOp->token == BetweenBrackets || (lastOp->token == CallArgs && !isLastVarSet(lastOp))) {
|
||||||
|
op.token = EquationSeperator;
|
||||||
|
op.lineNumber = lineNumber;
|
||||||
|
vecAdd(&lastFunc->operations, op);
|
||||||
|
op.token = Variable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenType == Token_Variable) {
|
||||||
|
u8 stdLen = 0;
|
||||||
|
ClassFunctionTableEntry_t* cfte = searchStdLib(var, &stdLen);
|
||||||
|
|
||||||
|
if (cfte == NULL) {
|
||||||
|
CreateVariableReferenceStr(var);
|
||||||
|
op.variable = reference;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VariableReference_t reference = { .staticVariableType = 3, .staticFunction = cfte, .staticFunctionLen = stdLen };
|
||||||
|
op.variable = reference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tokenType == Token_Int) {
|
||||||
|
/*
|
||||||
|
Variable_t a = newIntVariable(*((s64*)var));
|
||||||
|
a.gcDoNotFree = 1;
|
||||||
|
free(var);
|
||||||
|
vecAdd(&staticVariableHolder, a);
|
||||||
|
CreateVariableReferenceStatic((Variable_t*)(staticVariableHolder.count - 1));
|
||||||
|
*/
|
||||||
|
|
||||||
|
VariableReference_t reference = { .staticVariableType = 1, .integerType = *((s64*)var) };
|
||||||
|
op.variable = reference;
|
||||||
|
free(var);
|
||||||
|
}
|
||||||
|
else if (tokenType == Token_String) {
|
||||||
|
/*
|
||||||
|
Variable_t a = newStringVariable(var, 1, 1);
|
||||||
|
a.gcDoNotFree = 1;
|
||||||
|
vecAdd(&staticVariableHolder, a);
|
||||||
|
CreateVariableReferenceStatic((Variable_t*)(staticVariableHolder.count - 1));
|
||||||
|
*/
|
||||||
|
|
||||||
|
VariableReference_t reference = { .staticVariableType = 2, .stringType = var };
|
||||||
|
op.variable = reference;
|
||||||
|
}
|
||||||
|
else if (tokenType == Token_Token) {
|
||||||
|
u8 token = (u8)var;
|
||||||
|
|
||||||
|
if (token == Equals && lastOp) {
|
||||||
|
if (lastOp->token == Variable) {
|
||||||
|
if (lastOp->variable.staticVariableSet) {
|
||||||
|
SCRIPT_PARSER_ERR("Trying to assign to a static variable");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setNextActionOperator(&lastFunc->operations, ActionSet, ActionExtraNone, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lastOp->token == CallArgs) {
|
||||||
|
CallArgs_t* last = getLastRef(&lastOp->callArgs);
|
||||||
|
last->action = ActionSet;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCRIPT_PARSER_ERR("Trying to assign to non-object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (token == LeftCurlyBracket) {
|
||||||
|
Function_t templateFunction = createEmptyFunction();
|
||||||
|
vecAdd(&functionStack, templateFunction);
|
||||||
|
|
||||||
|
StackHistory_t functionHistory = History_Function;
|
||||||
|
vecAdd(&stackHistoryHolder, functionHistory);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (token == RightCurlyBracket) {
|
||||||
|
if (stackHistoryHolder.count != 1 && *lastHistory == History_Function) {
|
||||||
|
Function_t *popFunc = popStackEntry(&functionStack);
|
||||||
|
popStackEntry(&stackHistoryHolder);
|
||||||
|
|
||||||
|
lastFunc = getStackEntry(&functionStack);
|
||||||
|
|
||||||
|
if (lastFunc) { // TODO: Add check for null deref
|
||||||
|
lastOp = getStackEntry(&lastFunc->operations);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastOp && (lastOp->token == Variable || (lastOp->token == CallArgs && !isLastVarSet(lastOp)))) {
|
||||||
|
if (lastOp->token == Variable) {
|
||||||
|
SCRIPT_PARSER_ERR("GET variable before {}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set last arg to {}
|
||||||
|
CallArgs_t* lastCall = getLastRef(&lastOp->callArgs);
|
||||||
|
if (lastCall->extraAction == ActionExtraCallArgs) {
|
||||||
|
Function_t* funcArgs = lastCall->extra;
|
||||||
|
if (funcArgs->operations.count != 0) {
|
||||||
|
op.token = EquationSeperator;
|
||||||
|
op.lineNumber = lineNumber;
|
||||||
|
vecAdd(&funcArgs->operations, op);
|
||||||
|
op.token = Variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable_t a = newFunctionVariable(createFunctionClass(*popFunc, NULL));
|
||||||
|
vecAdd(&staticVariableHolder, a);
|
||||||
|
CreateVariableReferenceStatic((Variable_t*)(staticVariableHolder.count - 1));
|
||||||
|
op.variable = reference;
|
||||||
|
vecAdd(&funcArgs->operations, op);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Variable_t a = newFunctionVariable(createFunctionClass(*popFunc, NULL));
|
||||||
|
vecAdd(&staticVariableHolder, a);
|
||||||
|
CreateVariableReferenceStatic((Variable_t*)(staticVariableHolder.count - 1));
|
||||||
|
op.variable = reference;
|
||||||
|
vecAdd(&lastFunc->operations, op);
|
||||||
|
|
||||||
|
op.token = EquationSeperator;
|
||||||
|
op.lineNumber = lineNumber;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCRIPT_PARSER_ERR("Stack count is 1 or state is not a function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (token == Dot) {
|
||||||
|
if (lastOp && (lastOp->token == Variable || lastOp->token == BetweenBrackets || (lastOp->token == CallArgs && !isLastVarSet(lastOp)))) {
|
||||||
|
tokenType = nextToken(&in, &var);
|
||||||
|
if (tokenType != Token_Variable) {
|
||||||
|
SCRIPT_PARSER_ERR("Acessing member with non-dynamic token");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setNextActionOperator(&lastFunc->operations, ActionGet, ActionExtraMemberName, var);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCRIPT_PARSER_ERR("Member access on non-variable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (token == LeftBracket) {
|
||||||
|
Function_t templateFunction = createEmptyFunction();
|
||||||
|
vecAdd(&functionStack, templateFunction);
|
||||||
|
|
||||||
|
StackHistory_t functionHistory = History_Bracket;
|
||||||
|
vecAdd(&stackHistoryHolder, functionHistory);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (token == RightBracket) {
|
||||||
|
if (*lastHistory == History_Bracket) {
|
||||||
|
Function_t* bstack = popStackEntry(&functionStack);
|
||||||
|
popStackEntry(&stackHistoryHolder);
|
||||||
|
lastFunc = getStackEntry(&functionStack);
|
||||||
|
|
||||||
|
if (lastFunc) { // TODO: Add check for null deref
|
||||||
|
lastOp = getStackEntry(&lastFunc->operations);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastOp && (lastOp->token == Variable || lastOp->token == BetweenBrackets || (lastOp->token == CallArgs && !isLastVarSet(lastOp) && !isLastVarCall(lastOp)))) {
|
||||||
|
Function_t* newBStack = malloc(sizeof(Function_t));
|
||||||
|
*newBStack = *bstack;
|
||||||
|
setNextActionOperator(&lastFunc->operations, ActionCall, ActionExtraCallArgs, newBStack); // Maybe pass NULL if array is empty?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (lastOp && isLastVarCall(lastOp)) {
|
||||||
|
op.token = EquationSeperator;
|
||||||
|
vecAdd(&lastFunc->operations, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!countTokens(bstack, EquationSeperator)) {
|
||||||
|
op.variable.betweenBrackets.data = bstack->operations.data;
|
||||||
|
op.variable.betweenBrackets.len = bstack->operations.count;
|
||||||
|
op.token = BetweenBrackets;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCRIPT_PARSER_ERR("Priority brackets can only contain 1 argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCRIPT_PARSER_ERR(") without (");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (token == LeftSquareBracket) {
|
||||||
|
Function_t templateFunction = createEmptyFunction();
|
||||||
|
vecAdd(&functionStack, templateFunction);
|
||||||
|
|
||||||
|
StackHistory_t functionHistory = History_Array;
|
||||||
|
vecAdd(&stackHistoryHolder, functionHistory);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (token == RightSquareBracket) {
|
||||||
|
if (*lastHistory == History_Array) {
|
||||||
|
Function_t* astack = popStackEntry(&functionStack);
|
||||||
|
popStackEntry(&stackHistoryHolder);
|
||||||
|
lastFunc = getStackEntry(&functionStack);
|
||||||
|
|
||||||
|
if (lastFunc) { // TODO: Add check for null deref
|
||||||
|
lastOp = getStackEntry(&lastFunc->operations);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastOp && (lastOp->token == Variable || (lastOp->token == CallArgs && !isLastVarSet(lastOp)))) {
|
||||||
|
if (!countTokens(astack, EquationSeperator)) {
|
||||||
|
Function_t* newAStack = malloc(sizeof(Function_t));
|
||||||
|
*newAStack = *astack;
|
||||||
|
setNextActionOperator(&lastFunc->operations, ActionGet, ActionExtraArrayIndex, newAStack);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// We're just assuming that it's a new array lol
|
||||||
|
|
||||||
|
op.token = EquationSeperator;
|
||||||
|
vecAdd(&lastFunc->operations, op);
|
||||||
|
op.token = Variable;
|
||||||
|
|
||||||
|
|
||||||
|
Variable_t a = createUnsolvedArrayVariable(astack);
|
||||||
|
vecAdd(&staticVariableHolder, a);
|
||||||
|
CreateVariableReferenceStatic((Variable_t*)(staticVariableHolder.count - 1));
|
||||||
|
op.variable = reference;
|
||||||
|
|
||||||
|
//gfx_printf("[FATAL] indexes cannot contain mutiple arguments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: optimize output to a typed array, if possible
|
||||||
|
Variable_t a = createUnsolvedArrayVariable(astack);
|
||||||
|
vecAdd(&staticVariableHolder, a);
|
||||||
|
CreateVariableReferenceStatic((Variable_t*)(staticVariableHolder.count - 1));
|
||||||
|
op.variable = reference;
|
||||||
|
/*
|
||||||
|
vecAdd(&lastFunc->operations, op);
|
||||||
|
op.token = EquationSeperator;
|
||||||
|
op.lineNumber = lineNumber;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SCRIPT_PARSER_ERR("] without [");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (token == Not) {
|
||||||
|
notNext = !notNext;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
op.token = token;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < tokenConvertionCount; i++) {
|
||||||
|
if (token == tokenConvertions[i].token) {
|
||||||
|
op.tokenStr = tokenConvertions[i].strToken;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notNext) {
|
||||||
|
op.not = 1;
|
||||||
|
notNext = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vecAdd(&lastFunc->operations, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functionStack.count != 1 || stackHistoryHolder.count != 1) {
|
||||||
|
SCRIPT_PARSER_ERR("There seems to be an open bracket somewhere. EOF reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ParserRet_t parse = { .main = (*(Function_t*)getStackEntry(&functionStack)), .staticVarHolder = staticVariableHolder, .valid = 1 };
|
||||||
|
|
||||||
|
vecFree(functionStack);
|
||||||
|
vecFree(stackHistoryHolder);
|
||||||
|
scriptCurrentLine = 1;
|
||||||
|
return parse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void exitFunction(Operator_t* start, u32 len) {
|
||||||
|
for (u32 i = 0; i < len; i++) {
|
||||||
|
if (start[i].token == Variable) {
|
||||||
|
if (start[i].variable.staticVariableOptionsUnion == 0) {
|
||||||
|
FREE(start[i].variable.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start[i].variable.staticVariableType == 2) {
|
||||||
|
FREE(start[i].variable.stringType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (start[i].token == BetweenBrackets) {
|
||||||
|
exitFunction(start[i].variable.betweenBrackets.data, start[i].variable.betweenBrackets.len);
|
||||||
|
FREE(start[i].variable.betweenBrackets.data);
|
||||||
|
}
|
||||||
|
else if (start[i].token == CallArgs) {
|
||||||
|
CallArgs_t* call = &start[i].callArgs;
|
||||||
|
|
||||||
|
while (call != NULL) {
|
||||||
|
if (call->extraAction == ActionExtraArrayIndex) {
|
||||||
|
Function_t* f = call->extra;
|
||||||
|
exitFunction(f->operations.data, f->operations.count);
|
||||||
|
vecFree(f->operations);
|
||||||
|
FREE(f);
|
||||||
|
}
|
||||||
|
else if (call->extraAction == ActionExtraMemberName) {
|
||||||
|
FREE(call->extra);
|
||||||
|
}
|
||||||
|
else if (call->extraAction == ActionExtraCallArgs) {
|
||||||
|
Function_t* f = call->extra;
|
||||||
|
exitFunction(f->operations.data, f->operations.count);
|
||||||
|
vecFree(f->operations);
|
||||||
|
FREE(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
CallArgs_t* nextCall = call->next;
|
||||||
|
if (call != &start[i].callArgs) {
|
||||||
|
FREE(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
call = nextCall;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void exitStaticVars(Vector_t* v) {
|
||||||
|
vecForEach(Variable_t*, staticVar, v) {
|
||||||
|
if (staticVar->variableType == FunctionClass) {
|
||||||
|
if (!staticVar->function.builtIn) {
|
||||||
|
exitFunction(staticVar->function.function.operations.data, staticVar->function.function.operations.count);
|
||||||
|
vecFree(staticVar->function.function.operations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
freeVariableInternal(staticVar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
#include "types.h"
|
typedef struct {
|
||||||
|
Function_t main;
|
||||||
|
Vector_t staticVarHolder;
|
||||||
|
u8 valid;
|
||||||
|
} ParserRet_t;
|
||||||
|
|
||||||
scriptResult_t mainLoop(scriptCtx_t* ctx);
|
#define SCRIPT_PARSER_ERR(message, ...) printScriptError(SCRIPT_PARSER_FATAL, message, ##__VA_ARGS__); return (ParserRet_t){0}
|
||||||
void printError(scriptResult_t res);
|
|
||||||
|
void exitStaticVars(Vector_t* v);
|
||||||
|
void exitFunction(Operator_t* start, u32 len);
|
||||||
|
ParserRet_t parseScript(char* in, u32 len);
|
||||||
|
char* utils_copyStringSize(const char* in, int size);
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user