Compare commits
116 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee8854fa14 | ||
|
|
11ca71cbc7 | ||
|
|
3794c61ab2 | ||
|
|
dde3ca2d73 | ||
|
|
9850dc305c | ||
|
|
4d1b59c05b | ||
|
|
a0c3323b7c | ||
|
|
c9e53d4b1d | ||
|
|
1a89246e7f | ||
|
|
2094ac2bba | ||
|
|
f9b0ff70f7 | ||
|
|
d2d3597c29 | ||
|
|
4b62b1f69f | ||
|
|
91c2c891fd | ||
|
|
1ba0a7d264 | ||
|
|
5f6bf332d3 | ||
|
|
448cc49cff | ||
|
|
81f0c0a0dc | ||
|
|
95c1046765 | ||
|
|
2a8c27115c | ||
|
|
b6933013be | ||
|
|
a2bb576c03 | ||
|
|
c8d6da5a23 | ||
|
|
f09263d3be | ||
|
|
fdfd383c34 | ||
|
|
39a32fc83d | ||
|
|
c072041039 | ||
|
|
6d75f96ed5 | ||
|
|
ab304c9178 | ||
|
|
abcb1dec46 | ||
|
|
ac4bf9cf2c | ||
|
|
72a51f9506 | ||
|
|
d50a77f861 | ||
|
|
0ecd6b16b0 | ||
|
|
4dcbaa8c2b | ||
|
|
2261dbce83 | ||
|
|
53ff1102df | ||
|
|
b01b49aff4 | ||
|
|
c9a7659d93 | ||
|
|
4f75cd62e5 | ||
|
|
2a74715c3c | ||
|
|
1210c3e689 | ||
|
|
a3f430c224 | ||
|
|
2f7be43ccb | ||
|
|
f5432c734c | ||
|
|
5ca35aa4fc | ||
|
|
2dd474ad26 | ||
|
|
97e45346ea | ||
|
|
6c1ce41900 | ||
|
|
4a57901746 | ||
|
|
c32636b8cb | ||
|
|
190ffdaa5a | ||
|
|
bdd2b40c96 | ||
|
|
53f54cf23b | ||
|
|
474d531788 | ||
|
|
3db55df0a6 | ||
|
|
1483a61f11 | ||
|
|
7b715f7be9 | ||
|
|
56034f9aac | ||
|
|
7e96a4dd3a | ||
|
|
523c81f797 | ||
|
|
f540c8250b | ||
|
|
e89b7f12dd | ||
|
|
279b67fa49 | ||
|
|
11f1f65ed1 | ||
|
|
071dfa9792 | ||
|
|
3cecb03dac | ||
|
|
a7c64f8ba2 | ||
|
|
6749dad1a4 | ||
|
|
91b4c86bbe | ||
|
|
aadb88eeea | ||
|
|
2c4d6552e9 | ||
|
|
c2e8d51115 | ||
|
|
1d69809022 | ||
|
|
093f14923c | ||
|
|
63768ccc99 | ||
|
|
a00f25d2f9 | ||
|
|
54faa38920 | ||
|
|
ae1bb909b6 | ||
|
|
ecb616e411 | ||
|
|
8c762c52e2 | ||
|
|
e14a7d1d4d | ||
|
|
08c81fe1f8 | ||
|
|
63be93be64 | ||
|
|
de4891e133 | ||
|
|
8fd398f213 | ||
|
|
ec53aa86dd | ||
|
|
51985ed2ca | ||
|
|
67ae7b9dcb | ||
|
|
96654d9620 | ||
|
|
ce97b97c8d | ||
|
|
034f680a8e | ||
|
|
7d17e34dee | ||
|
|
d0a16a49b6 | ||
|
|
5442547a59 | ||
|
|
10e7e06048 | ||
|
|
eac6426125 | ||
|
|
88b01994bd | ||
|
|
66780bb4c2 | ||
|
|
7f26981fa1 | ||
|
|
5b0a0070c7 | ||
|
|
0462f3b252 | ||
|
|
9a5cfdff4c | ||
|
|
cb3b1bf6e1 | ||
|
|
b4d2df8111 | ||
|
|
cadb95e3ce | ||
|
|
f148757110 | ||
|
|
6e538cd291 | ||
|
|
62a73ee612 | ||
|
|
4160037c81 | ||
|
|
3fa537e54a | ||
|
|
f35c18a0c2 | ||
|
|
aff137ac34 | ||
|
|
6236b0ab00 | ||
|
|
ae656a0f81 | ||
|
|
6a6648d3b3 |
7
Makefile
7
Makefile
@@ -20,7 +20,7 @@ VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wild
|
||||
|
||||
# Main and graphics.
|
||||
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
start.o \
|
||||
start.o exception_handlers.o \
|
||||
main.o heap.o \
|
||||
gfx.o tui.o \
|
||||
fe_emmc_tools.o fe_info.o fe_tools.o \
|
||||
@@ -28,9 +28,10 @@ OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
|
||||
# Hardware.
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
bpmp.o clock.o cluster.o di.o gpio.o i2c.o mc.o sdram.o pinmux.o se.o smmu.o tsec.o uart.o \
|
||||
bpmp.o clock.o cluster.o di.o gpio.o i2c.o irq.o mc.o sdram.o \
|
||||
pinmux.o se.o smmu.o tsec.o uart.o \
|
||||
fuse.o kfuse.o minerva.o \
|
||||
sdmmc.o sdmmc_driver.o emummc.o nx_emmc.o \
|
||||
sdmmc.o sdmmc_driver.o emummc.o nx_emmc.o nx_sd.o \
|
||||
bq24193.o max17050.o max7762x.o max77620-rtc.o \
|
||||
hw_init.o \
|
||||
)
|
||||
|
||||
64
README.md
64
README.md
@@ -53,14 +53,23 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
|
||||
| autoboot=0 | 0: Disable, #: Boot entry number to auto boot. |
|
||||
| autoboot_list=0 | 0: Read `autoboot` boot entry from hekate_ipl.ini, 1: Read from ini folder (ini files are ASCII ordered). |
|
||||
| bootwait=3 | 0: Disable (It also disables bootlogo. Having **VOL-** pressed since injection goes to menu.), #: Time to wait for **VOL-** to enter menu. |
|
||||
| verification=2 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and not 100% reliable), 2: Full (sha256 based, slow and 100% reliable). |
|
||||
| autohosoff=1 | 0: Disable, 1: If woke up from HOS via an RTC alarm, shows logo, then powers off completely, 2: No logo, immediately powers off.|
|
||||
| autonogc=1 | 0: Disable, 1: Automatically applies nogc patch if unburnt fuses found and a >= 4.0.0 HOS is booted. |
|
||||
| updater2p=0 | 0: Disable, 1: Force updates (if needed) the reboot2payload binary to be hekate. |
|
||||
| backlight=100 | Screen backlight level. 0-255. |
|
||||
|
||||
|
||||
### Possible boot entry key/value combinations:
|
||||
### Nyx Global Configuration keys/values for (nyx.ini):
|
||||
|
||||
| Config option | Description |
|
||||
| ------------------ | ---------------------------------------------------------- |
|
||||
| themecolor=167 | Sets Nyx color of text highlights. |
|
||||
| timeoff=100 | Sets time offset in HEX. Must be in HOS epoch format |
|
||||
| homescreen=0 | Sets home screen. 0: Home menu, 1: All configs (merges Launch and More configs), 2: Launch, 3: More Configs. |
|
||||
| verification=1 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and mostly reliable), 2: Full (sha256 based, slow and 100% reliable). |
|
||||
|
||||
|
||||
### Boot entry key/value combinations:
|
||||
|
||||
| Config option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------- |
|
||||
@@ -75,15 +84,26 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
|
||||
| fullsvcperm=1 | Disables SVC verification (full services permission) |
|
||||
| debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. |
|
||||
| atmosphere=1 | Enables Atmosphère patching. |
|
||||
| nouserexceptions=1 | Disables usermode exception handlers when paired with Exosphère. |
|
||||
| userpmu=1 | Allows user access to PMU when paired with Exosphère. |
|
||||
| emummc_force_disable=1 | Disabled emuMMC if it's enabled. |
|
||||
| stock=1 | Disables unneeded kernel patching when running stock or semi-stock. `If emuMMC is enabled, emummc_force_disabled=1` is required to run completely stock. |
|
||||
| emupath={SD folder} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. |
|
||||
| emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
|
||||
| emummc_force_disable=1 | Disables emuMMC if it's enabled. |
|
||||
| stock=1 | Disables unneeded kernel patching when running stock or semi-stock. `If emuMMC is enabled, emummc_force_disabled=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
|
||||
| id=idname | Identifies boot entry for forced boot via id. Max 7 chars. |
|
||||
| payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. |
|
||||
| logopath={SD path} | If no logopath, `bootloader/bootlogo.bmp` will be used if exists. If logopath exists, it will load the specified bitmap. |
|
||||
| icon={SD path} | Force Nyx to use the icon defined here. If this is not found, it will check for a bmp named as the boot entry ([Test 2] -> `bootloader/res/Test 2.bmp`). Otherwise default will be used. |
|
||||
|
||||
|
||||
### Boot entry key/value Exosphère combinations:
|
||||
|
||||
| Config option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------- |
|
||||
| nouserexceptions=1 | Disables usermode exception handlers when paired with Exosphère. |
|
||||
| userpmu=1 | Enables user access to PMU when paired with Exosphère. |
|
||||
| cal0blank=1 | Overrides Exosphère config `blank_prodinfo_{sys/emu}mmc`. If that key doesn't exist, `exosphere.ini` will be used. |
|
||||
| cal0writesys=1 | Overrides Exosphère config `allow_writing_to_cal_sysmmc`. If that key doesn't exist, `exosphere.ini` will be used. |
|
||||
|
||||
|
||||
**Note1**: When using the wildcard (`/*`) with `kip1` you can still use the normal `kip1` after that to load extra single kips.
|
||||
|
||||
**Note2**: When using FSS0 it parses exosphere, warmboot and all core kips. You can override the first 2 by using `secmon`/`warmboot` after defining `fss0`.
|
||||
@@ -97,32 +117,36 @@ This is in case the kips are incompatible between them. If compatible, you can o
|
||||
|
||||
hekate has a boot storage in the binary that helps it configure it outside of BPMP enviroment:
|
||||
|
||||
| Offset / Name | Description |
|
||||
| -------------------- | ----------------------------------------------------------------- |
|
||||
| '0x94' boot_cfg | bit0: Force AutoBoot, bit1: Show launch log, bit2: Boot from ID, bit7: sept run. |
|
||||
| '0x95' autoboot | If `Force AutoBoot`: 0: Force go to menu, else boot that entry. |
|
||||
| '0x96' autoboot_list | If `Force AutoBoot` and `autoboot` then it boots from ini folder. |
|
||||
| '0x97' extra_cfg | bit7: Force Nyx to run `Dump pkg1/2`. |
|
||||
| '0x98' id[8] | When Boot from ID is set, it will search all inis automatically and find the boot entry with that id and boot it. Must be NULL terminated. |
|
||||
| '0x98' xt_str[128] | Depends on the set cfg bits. |
|
||||
| Offset / Name | Description |
|
||||
| ----------------------- | ----------------------------------------------------------------- |
|
||||
| '0x94' boot_cfg | bit0: `Force AutoBoot`, bit1: `Show launch log`, bit2: Boot from ID, bit3: `Boot to emuMMC`, bit7: `sept run`. |
|
||||
| '0x95' autoboot | If `Force AutoBoot`: 0: Force go to menu, else boot that entry. |
|
||||
| '0x96' autoboot_list | If `Force AutoBoot` and `autoboot` then it boots from ini folder. |
|
||||
| '0x97' extra_cfg | bit7: Force Nyx to run `Dump pkg1/2`. |
|
||||
| '0x98' xt_str[128] | Depends on the set cfg bits. |
|
||||
| '0x98' id[8] | When `Boot from ID` is set, it will search all inis automatically and find the boot entry with that id and boot it. Must be NULL terminated. |
|
||||
| '0xA0' emummc_path[120] | When `Boot to emuMMC` is set, it will override the current emuMMC (boot entry or emummc.ini). Must be NULL terminated. |
|
||||
|
||||
|
||||
If the main .ini is not found, it is created on the first hekate boot.
|
||||
|
||||
|
||||
```
|
||||
hekate (C) 2018 naehrwert, st4rk
|
||||
CTCaer mod (C) 2018 CTCaer.
|
||||
hekate (c) 2018, naehrwert, st4rk.
|
||||
(c) 2018-2020, CTCaer.
|
||||
|
||||
Nyx GUI (c) 2019-2020, CTCaer.
|
||||
|
||||
Thanks to: derrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8.
|
||||
Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.
|
||||
|
||||
Open source and free packages used:
|
||||
- FatFs R0.13a, Copyright (C) 2017, ChaN
|
||||
- bcl-1.2.0, Copyright (C) 2003-2006, Marcus Geelnard
|
||||
- FatFs R0.13a, Copyright (c) 2017, ChaN
|
||||
- bcl-1.2.0, Copyright (c) 2003-2006, Marcus Geelnard
|
||||
- Atmosphère (Exosphere types/panic, prc id kernel patches),
|
||||
Copyright (C) 2018-2019, Atmosphère-NX
|
||||
- elfload, Copyright (C) 2014 Owen Shepherd, Copyright (C) 2018 M4xw
|
||||
Copyright (c) 2018-2019, Atmosphère-NX
|
||||
- elfload, Copyright (c) 2014 Owen Shepherd, Copyright (c) 2018 M4xw
|
||||
- Littlev Graphics Library, Copyright (c) 2016 Gabor Kiss-Vamosi
|
||||
|
||||
___
|
||||
.-' `'.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# IPL Version.
|
||||
BLVERSION_MAJOR := 5
|
||||
BLVERSION_MINOR := 1
|
||||
BLVERSION_HOTFX := 4
|
||||
BLVERSION_MINOR := 2
|
||||
BLVERSION_HOTFX := 0
|
||||
BLVERSION_RSVD := 0
|
||||
|
||||
# Nyx Version.
|
||||
NYXVERSION_MAJOR := 0
|
||||
NYXVERSION_MINOR := 8
|
||||
NYXVERSION_HOTFX := 7
|
||||
NYXVERSION_MINOR := 9
|
||||
NYXVERSION_HOTFX := 0
|
||||
NYXVERSION_RSVD := 0
|
||||
|
||||
@@ -23,14 +23,13 @@
|
||||
#include "../gfx/tui.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/list.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount();
|
||||
|
||||
void set_default_configuration()
|
||||
{
|
||||
@@ -46,6 +45,7 @@ void set_default_configuration()
|
||||
h_cfg.brand = NULL;
|
||||
h_cfg.tagline = NULL;
|
||||
h_cfg.errors = 0;
|
||||
h_cfg.eks = NULL;
|
||||
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
|
||||
h_cfg.rcm_patched = true;
|
||||
h_cfg.emummc_force_disable = false;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#include "../hos/hos.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
typedef struct _hekate_config
|
||||
@@ -38,6 +39,7 @@ typedef struct _hekate_config
|
||||
bool rcm_patched;
|
||||
u32 sbar_time_keeping;
|
||||
u32 errors;
|
||||
hos_eks_mbr_t *eks;
|
||||
} hekate_config;
|
||||
|
||||
void set_default_configuration();
|
||||
|
||||
@@ -55,12 +55,9 @@ u32 _find_section_name(char *lbuf, u32 lblen, char schar)
|
||||
ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type)
|
||||
{
|
||||
if (csec)
|
||||
{
|
||||
list_append(dst, &csec->link);
|
||||
csec = NULL;
|
||||
}
|
||||
|
||||
csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
|
||||
csec = (ini_sec_t *)calloc(sizeof(ini_sec_t), 1);
|
||||
csec->name = _strdup(name);
|
||||
csec->type = type;
|
||||
|
||||
@@ -154,7 +151,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
{
|
||||
u32 i = _find_section_name(lbuf, lblen, '=');
|
||||
|
||||
ini_kv_t *kv = (ini_kv_t *)malloc(sizeof(ini_kv_t));
|
||||
ini_kv_t *kv = (ini_kv_t *)calloc(sizeof(ini_kv_t), 1);
|
||||
kv->key = _strdup(&lbuf[0]);
|
||||
kv->val = _strdup(&lbuf[i + 1]);
|
||||
list_append(&csec->kvs, &kv->link);
|
||||
|
||||
233
bootloader/exception_handlers.S
Normal file
233
bootloader/exception_handlers.S
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Armv7tdmi Status register.
|
||||
*
|
||||
* bit0: Mode 0.
|
||||
* bit1: Mode 1.
|
||||
* bit2: Mode 2.
|
||||
* bit3: Mode 3.
|
||||
* bit4: Mode 4.
|
||||
* bit5: Thumb state.
|
||||
* bit6: FIQ disable.
|
||||
* bit7: IRQ disable.
|
||||
* bit8-27: Reserved.
|
||||
* bit28: Overflow condition.
|
||||
* bit29: Carry/Borrow/Extend condition.
|
||||
* bit30: Zero condition.
|
||||
* bit31: Negative/Less than condition.
|
||||
*
|
||||
* M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers
|
||||
* 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||
* 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq
|
||||
* 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq
|
||||
* 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc
|
||||
* 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
|
||||
* 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und
|
||||
* 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||
*/
|
||||
|
||||
#define EXCP_EN_ADDR 0x4003FFFC
|
||||
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||||
#define EXCP_LR_ADDR 0x4003FFF4
|
||||
|
||||
#define EXCP_VEC_BASE 0x6000F000
|
||||
#define EVP_COP_RESET_VECTOR 0x200
|
||||
#define EVP_COP_UNDEF_VECTOR 0x204
|
||||
#define EVP_COP_SWI_VECTOR 0x208
|
||||
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
|
||||
#define EVP_COP_DATA_ABORT_VECTOR 0x210
|
||||
#define EVP_COP_RSVD_VECTOR 0x214
|
||||
#define EVP_COP_IRQ_VECTOR 0x218
|
||||
#define EVP_COP_FIQ_VECTOR 0x21C
|
||||
|
||||
#define MODE_USR 0x10
|
||||
#define MODE_FIQ 0x11
|
||||
#define MODE_IRQ 0x12
|
||||
#define MODE_SVC 0x13
|
||||
#define MODE_ABT 0x17
|
||||
#define MODE_UDF 0x1B
|
||||
#define MODE_SYS 0x1F
|
||||
#define MODE_MASK 0x1F
|
||||
|
||||
#define FIQ 0x40
|
||||
#define IRQ 0x80
|
||||
|
||||
.section .text._irq_setup
|
||||
.arm
|
||||
|
||||
.extern ipl_main
|
||||
.type ipl_main, %function
|
||||
|
||||
.extern svc_handler
|
||||
.type svc_handler, %function
|
||||
|
||||
.extern irq_handler
|
||||
.type irq_handler, %function
|
||||
|
||||
.extern fiq_setup
|
||||
.type fiq_setup, %function
|
||||
|
||||
.extern fiq_handler
|
||||
.type fiq_handler, %function
|
||||
|
||||
.globl _irq_setup
|
||||
.type _irq_setup, %function
|
||||
_irq_setup:
|
||||
MRS R0, CPSR
|
||||
BIC R0, R0, #MODE_MASK /* Clear mode bits */
|
||||
ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */
|
||||
MSR CPSR, R0
|
||||
|
||||
/* Setup IRQ stack pointer */
|
||||
MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||
LDR SP, =0x40040000
|
||||
|
||||
/* Setup SYS stack pointer */
|
||||
MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||
LDR SP, =0x4003FF00 /* Will be changed later to DRAM */
|
||||
|
||||
MOV LR, PC
|
||||
BL setup_vectors
|
||||
/*BL fiq_setup*/
|
||||
|
||||
/* Enable interrupts */
|
||||
BL irq_enable_cpu_irq_exceptions
|
||||
|
||||
B ipl_main
|
||||
B .
|
||||
|
||||
_reset:
|
||||
LDR R0, =EXCP_EN_ADDR
|
||||
LDR R1, =0x30505645 /* EVP0 */
|
||||
STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */
|
||||
LDR R0, =EXCP_LR_ADDR
|
||||
MOV R1, LR
|
||||
STR R1, [R0] /* Save LR in EXCP_LR_ADDR */
|
||||
LDR R0, =__bss_start
|
||||
EOR R1, R1, R1
|
||||
LDR R2, =__bss_end
|
||||
SUB R2, R2, R0
|
||||
BL memset
|
||||
B _irq_setup
|
||||
|
||||
_reset_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x545352 /* RST */
|
||||
STR R1, [R0] /* RST in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
_undefined_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x464455 /* UDF */
|
||||
STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
_prefetch_abort_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x54424150 /* PABT */
|
||||
STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
_data_abort_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x54424144 /* DABT */
|
||||
STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
.globl irq_enable_cpu_irq_exceptions
|
||||
.type irq_enable_cpu_irq_exceptions, %function
|
||||
irq_enable_cpu_irq_exceptions:
|
||||
MRS R12, CPSR
|
||||
BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */
|
||||
MSR CPSR, R12
|
||||
BX LR
|
||||
|
||||
.globl irq_disable_cpu_irq_exceptions
|
||||
.type irq_disable_cpu_irq_exceptions, %function
|
||||
irq_disable_cpu_irq_exceptions:
|
||||
MRS R12, CPSR
|
||||
ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */
|
||||
MSR CPSR, R12
|
||||
BX LR
|
||||
|
||||
_irq_handler:
|
||||
MOV R13, R0 /* Save R0 in R13_IRQ */
|
||||
SUB R0, LR, #4 /* Put return address in R0_SYS */
|
||||
MOV LR, R1 /* Save R1 in R14_IRQ (LR) */
|
||||
MRS R1, SPSR /* Put the SPSR in R1_SYS */
|
||||
|
||||
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||
STMFD SP!, {R0, R1} /* SPSR and PC */
|
||||
STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */
|
||||
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||
SUB SP, SP, #8 /* Make room for stacking R0 and R1 */
|
||||
|
||||
MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */
|
||||
STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */
|
||||
|
||||
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||
LDR R12, =irq_handler
|
||||
MOV LR, PC /* Copy the return address to link register */
|
||||
BX R12 /* Call the C IRQ handler (ARM/THUMB) */
|
||||
|
||||
MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||
ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */
|
||||
|
||||
MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||
MOV SP, R0 /* Copy SP_SYS to SP_IRQ */
|
||||
LDR R0, [SP, #28] /* Load the saved SPSR from the stack */
|
||||
MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */
|
||||
|
||||
LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */
|
||||
NOP /* Cant access barked registers immediately */
|
||||
LDR LR, [SP, #24] /* Load return address from the SYS stack */
|
||||
MOVS PC, LR /* Return restoring CPSR from SPSR */
|
||||
|
||||
_fiq_handler:
|
||||
BL fiq_handler
|
||||
|
||||
setup_vectors:
|
||||
/* Setup vectors */
|
||||
LDR R0, =EXCP_VEC_BASE
|
||||
|
||||
LDR R1, =_reset_handler
|
||||
STR R1, [R0, #EVP_COP_RESET_VECTOR]
|
||||
|
||||
LDR R1, =_undefined_handler
|
||||
STR R1, [R0, #EVP_COP_UNDEF_VECTOR]
|
||||
|
||||
LDR R1, =_reset_handler
|
||||
STR R1, [R0, #EVP_COP_SWI_VECTOR]
|
||||
|
||||
LDR R1, =_prefetch_abort_handler
|
||||
STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR]
|
||||
|
||||
LDR R1, =_data_abort_handler
|
||||
STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR]
|
||||
|
||||
LDR R1, =_reset_handler
|
||||
STR R1, [R0, #EVP_COP_RSVD_VECTOR]
|
||||
|
||||
LDR R1, =_irq_handler
|
||||
STR R1, [R0, #EVP_COP_IRQ_VECTOR]
|
||||
|
||||
LDR R1, =_fiq_handler
|
||||
STR R1, [R0, #EVP_COP_FIQ_VECTOR]
|
||||
|
||||
BX LR
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "../mem/heap.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/util.h"
|
||||
@@ -36,13 +37,8 @@
|
||||
#define OUT_FILENAME_SZ 128
|
||||
#define SHA256_SZ 0x20
|
||||
|
||||
extern sdmmc_t sd_sdmmc;
|
||||
extern sdmmc_storage_t sd_storage;
|
||||
extern FATFS sd_fs;
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount();
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
#pragma GCC push_options
|
||||
@@ -486,7 +482,7 @@ static void _dump_emmc_selected(emmcPartType_t dumpType)
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
@@ -525,7 +521,7 @@ static void _dump_emmc_selected(emmcPartType_t dumpType)
|
||||
|
||||
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER) || (dumpType & PART_RAW))
|
||||
{
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER))
|
||||
{
|
||||
@@ -837,7 +833,7 @@ static void _restore_emmc_selected(emmcPartType_t restoreType)
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
@@ -873,7 +869,7 @@ static void _restore_emmc_selected(emmcPartType_t restoreType)
|
||||
|
||||
if (restoreType & PART_GP_ALL)
|
||||
{
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
|
||||
@@ -34,16 +34,11 @@
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/mmc.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
extern sdmmc_storage_t sd_storage;
|
||||
extern FATFS sd_fs;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount();
|
||||
extern int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
#pragma GCC push_options
|
||||
@@ -145,7 +140,7 @@ void print_mmc_info()
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
@@ -158,21 +153,6 @@ void print_mmc_info()
|
||||
gfx_printf("%kCID:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
switch (storage.csd.mmca_vsn)
|
||||
{
|
||||
case 0: /* MMC v1.0 - v1.2 */
|
||||
case 1: /* MMC v1.4 */
|
||||
gfx_printf(
|
||||
" Vendor ID: %03X\n"
|
||||
" Model: %c%c%c%c%c%c%c\n"
|
||||
" HW rev: %X\n"
|
||||
" FW rev: %X\n"
|
||||
" S/N: %03X\n"
|
||||
" Month/Year: %02d/%04d\n\n",
|
||||
storage.cid.manfid,
|
||||
storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2],
|
||||
storage.cid.prod_name[3], storage.cid.prod_name[4], storage.cid.prod_name[5],
|
||||
storage.cid.prod_name[6], storage.cid.hwrev, storage.cid.fwrev,
|
||||
storage.cid.serial, storage.cid.month, storage.cid.year);
|
||||
break;
|
||||
case 2: /* MMC v2.0 - v2.2 */
|
||||
case 3: /* MMC v3.1 - v3.3 */
|
||||
case 4: /* MMC v4 */
|
||||
@@ -190,7 +170,6 @@ void print_mmc_info()
|
||||
storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year);
|
||||
break;
|
||||
default:
|
||||
EPRINTFARGS("eMMC has unknown MMCA version %d", storage.csd.mmca_vsn);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -263,7 +242,7 @@ void print_mmc_info()
|
||||
gfx_put_small_sep();
|
||||
gfx_printf("%kGPP (eMMC USER) partition table:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
int gpp_idx = 0;
|
||||
@@ -346,17 +325,17 @@ void print_tsec_key()
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
// Read package1.
|
||||
u8 *pkg1 = (u8 *)malloc(0x40000);
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
EPRINTF("Unknown pkg1 version for reading\nTSEC firmware.");
|
||||
EPRINTF("Unknown pkg1 version.");
|
||||
goto out_wait;
|
||||
}
|
||||
|
||||
@@ -448,7 +427,7 @@ void print_fuel_gauge_info()
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
gfx_printf("%kFuel Gauge IC Info:\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_printf("%kFuel Gauge Info:\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
max17050_get_property(MAX17050_RepSOC, &value);
|
||||
gfx_printf("Capacity now: %3d%\n", value >> 8);
|
||||
@@ -500,7 +479,7 @@ void print_battery_charger_info()
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
gfx_printf("%k\n\nBattery Charger IC Info:\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_printf("%k\n\nBattery Charger Info:\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
bq24193_get_property(BQ24193_InputVoltageLimit, &value);
|
||||
gfx_printf("Input voltage limit: %4d mV\n", value);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "../power/max7762x.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../utils/btn.h"
|
||||
@@ -40,9 +41,6 @@
|
||||
extern boot_cfg_t b_cfg;
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount();
|
||||
extern int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
#pragma GCC push_options
|
||||
@@ -69,12 +67,12 @@ void dump_packages12()
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out_free;
|
||||
}
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
// Read package1.
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
@@ -121,7 +119,7 @@ void dump_packages12()
|
||||
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
|
||||
|
||||
// Decrypt.
|
||||
keygen(keyblob, kb, &tsec_ctxt, NULL);
|
||||
hos_keygen(keyblob, kb, &tsec_ctxt, NULL);
|
||||
if (kb <= KB_FIRMWARE_VERSION_600)
|
||||
h_cfg.se_keygen_done = 1;
|
||||
free(keyblob);
|
||||
@@ -169,7 +167,7 @@ void dump_packages12()
|
||||
}
|
||||
|
||||
// Dump package2.1.
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
// Parse eMMC GPT.
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
@@ -264,14 +262,14 @@ void _toggle_autorcm(bool enable)
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
int i, sect = 0;
|
||||
u8 corr_mod_byte0;
|
||||
@@ -335,7 +333,7 @@ void menu_autorcm()
|
||||
sdmmc_t sdmmc;
|
||||
bool disabled = true;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
btn_wait();
|
||||
@@ -344,7 +342,7 @@ void menu_autorcm()
|
||||
}
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
|
||||
if ((fuse_read_odm(4) & 3) != 3)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-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,
|
||||
@@ -31,7 +31,11 @@
|
||||
|
||||
#include "di.inl"
|
||||
|
||||
static u32 _display_ver = 0;
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
static u32 _display_id = 0;
|
||||
|
||||
void display_end();
|
||||
|
||||
static void _display_dsi_wait(u32 timeout, u32 off, u32 mask)
|
||||
{
|
||||
@@ -41,8 +45,21 @@ static void _display_dsi_wait(u32 timeout, u32 off, u32 mask)
|
||||
usleep(5);
|
||||
}
|
||||
|
||||
static void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait)
|
||||
{
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = (param << 8) | cmd;
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
|
||||
if (wait)
|
||||
usleep(wait);
|
||||
}
|
||||
|
||||
void display_init()
|
||||
{
|
||||
// Check if display is already initialized.
|
||||
if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & 0x18000000)
|
||||
display_end();
|
||||
|
||||
// Power on.
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL);
|
||||
@@ -60,16 +77,16 @@ void display_init()
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000; // Set enable clock DSIA_LP.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz).
|
||||
|
||||
// Disable deap power down.
|
||||
// Disable deep power down.
|
||||
PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000;
|
||||
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
|
||||
|
||||
// Config LCD and Backlight pins.
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE; // PULL_DOWN | 1
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
|
||||
// Set Backlight +-5V pins mode and direction
|
||||
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
|
||||
@@ -87,14 +104,18 @@ void display_init()
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Enable Backlight EN.
|
||||
|
||||
// Power up supply regulator for display interface.
|
||||
MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG2) = 0;
|
||||
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0;
|
||||
|
||||
// Set DISP1 clock source and parrent clock.
|
||||
exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4);
|
||||
// Set DISP1 clock source and parent clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT.
|
||||
u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 96 MHz.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2D0AAA; // PLLD_ENABLE_CLK.
|
||||
|
||||
// Setup display communication interfaces.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_3, 61);
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_dc_setup_win_config, 94);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config, 61);
|
||||
usleep(10000);
|
||||
|
||||
// Enable Backlight Reset.
|
||||
@@ -103,12 +124,10 @@ void display_init()
|
||||
|
||||
// Setups DSI packet configuration and request display id.
|
||||
DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204;
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x337; // MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
_display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, 3, 0);
|
||||
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x406; // MIPI_DCS_GET_DISPLAY_ID
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_READ, MIPI_DCS_GET_DISPLAY_ID, 0);
|
||||
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||
|
||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
|
||||
@@ -116,37 +135,71 @@ void display_init()
|
||||
|
||||
usleep(5000);
|
||||
|
||||
_display_ver = DSI(_DSIREG(DSI_RD_DATA));
|
||||
if (_display_ver == 0x10)
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_4, 43);
|
||||
// MIPI_DCS_GET_DISPLAY_ID reply is a long read, size 3 u32.
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
_display_id = DSI(_DSIREG(DSI_RD_DATA)); // Skip ack and msg type info and get the payload (display id).
|
||||
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x1105; // MIPI_DCS_EXIT_SLEEP_MODE
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
// Save raw Display ID to Nyx storage.
|
||||
nyx_str->info.disp_id = _display_id;
|
||||
|
||||
usleep(180000);
|
||||
// Decode Display ID.
|
||||
_display_id = ((_display_id >> 8) & 0xFF00) | (_display_id & 0xFF);
|
||||
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x2905; // MIPI_DCS_SET_DISPLAY_ON
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
if ((_display_id & 0xFF) == PANEL_JDI_LPM062M)
|
||||
_display_id = PANEL_JDI_LPM062M;
|
||||
|
||||
usleep(20000);
|
||||
// Initialize display panel.
|
||||
switch (_display_id)
|
||||
{
|
||||
case PANEL_JDI_LPM062M:
|
||||
exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43);
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
case PANEL_AUO_A062TAN01:
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // Enable extension cmd. (Pass: FF 83 94).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x739; // MIPI_DSI_DCS_LONG_WRITE: 7 bytes.
|
||||
if (_display_id == PANEL_INL_P062CCA_AZ1)
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // Set Power control. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
|
||||
else
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x143209; // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ2:
|
||||
case PANEL_AUO_A062TAN02:
|
||||
default: // Allow spare part displays to work.
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 120000);
|
||||
break;
|
||||
}
|
||||
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
|
||||
|
||||
// Configure PLLD for DISP1.
|
||||
exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3);
|
||||
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 460.8 MHz.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN.
|
||||
|
||||
// Finalize DSI configuration.
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_5, 21);
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4;
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_7, 10);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 21);
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; // PCD1 | div3.
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10);
|
||||
usleep(10000);
|
||||
|
||||
// Calibrate display communication pads.
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_9, 4);
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16);
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_pad_cal_config, 6);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_pad_cal_config, 4);
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_apply_dsi_cal_config, 16);
|
||||
usleep(10000);
|
||||
|
||||
// Enable video display controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113);
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_enable_config, 113);
|
||||
}
|
||||
|
||||
void display_backlight_pwm_init()
|
||||
@@ -197,25 +250,50 @@ void display_end()
|
||||
{
|
||||
display_backlight_brightness(0, 1000);
|
||||
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1;
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE;
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; // MIPI_DCS_SET_DISPLAY_OFF
|
||||
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX;
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; // Disable host cmd packet.
|
||||
|
||||
// De-initialize video controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_13, 16);
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_disable_config, 17);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_timing_deinit_config, 16);
|
||||
usleep(10000);
|
||||
|
||||
// De-initialize display panel.
|
||||
if (_display_ver == 0x10)
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_14, 22);
|
||||
switch (_display_id)
|
||||
{
|
||||
case PANEL_JDI_LPM062M:
|
||||
exec_cfg((u32 *)DSI_BASE, _display_deinit_config_jdi, 22);
|
||||
break;
|
||||
case PANEL_AUO_A062TAN01:
|
||||
exec_cfg((u32 *)DSI_BASE, _display_deinit_config_auo, 37);
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ2:
|
||||
case PANEL_AUO_A062TAN02:
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // Enable extension cmd. (Pass: FF 83 94).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
// Set Power.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0xB39; // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
|
||||
if (_display_id == PANEL_INL_P062CCA_AZ2)
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // Set Power control. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
|
||||
else
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
|
||||
// Set Power control. (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG).
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x71143209;
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x114D31; // Set Power control. (Unknown).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x1005; // MIPI_DCS_ENTER_SLEEP_MODE
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
|
||||
usleep(50000);
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_ENTER_SLEEP_MODE, 50000);
|
||||
|
||||
// Disable display and backlight pins.
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-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,
|
||||
@@ -24,6 +24,21 @@
|
||||
/*! Display registers. */
|
||||
#define _DIREG(reg) ((reg) * 4)
|
||||
|
||||
// Display controller scratch registers.
|
||||
#define DC_D_WINBUF_DD_SCRATCH_REGISTER_0 0xED
|
||||
#define DC_D_WINBUF_DD_SCRATCH_REGISTER_1 0xEE
|
||||
#define DC_T_WINBUF_TD_SCRATCH_REGISTER_0 0x16D
|
||||
#define DC_T_WINBUF_TD_SCRATCH_REGISTER_1 0x16E
|
||||
#define DC_COM_SCRATCH_REGISTER_A 0x325
|
||||
#define DC_COM_SCRATCH_REGISTER_B 0x326
|
||||
#define DC_A_WINBUF_AD_SCRATCH_REGISTER_0 0xBED
|
||||
#define DC_A_WINBUF_AD_SCRATCH_REGISTER_1 0xBEE
|
||||
#define DC_B_WINBUF_BD_SCRATCH_REGISTER_0 0xDED
|
||||
#define DC_B_WINBUF_BD_SCRATCH_REGISTER_1 0xDEE
|
||||
#define DC_C_WINBUF_CD_SCRATCH_REGISTER_0 0xFED
|
||||
#define DC_C_WINBUF_CD_SCRATCH_REGISTER_1 0xFEE
|
||||
|
||||
// DC_CMD non-shadowed command/sync registers.
|
||||
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
|
||||
|
||||
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
|
||||
@@ -50,6 +65,7 @@
|
||||
#define PM0_ENABLE (1 << 16)
|
||||
#define PM1_ENABLE (1 << 18)
|
||||
|
||||
#define DC_CMD_INT_STATUS 0x37
|
||||
#define DC_CMD_INT_MASK 0x38
|
||||
#define DC_CMD_INT_ENABLE 0x39
|
||||
|
||||
@@ -62,11 +78,13 @@
|
||||
#define WIN_A_ACT_REQ (1 << 1)
|
||||
#define WIN_B_ACT_REQ (1 << 2)
|
||||
#define WIN_C_ACT_REQ (1 << 3)
|
||||
#define WIN_D_ACT_REQ (1 << 4)
|
||||
#define CURSOR_ACT_REQ (1 << 7)
|
||||
#define GENERAL_UPDATE (1 << 8)
|
||||
#define WIN_A_UPDATE (1 << 9)
|
||||
#define WIN_B_UPDATE (1 << 10)
|
||||
#define WIN_C_UPDATE (1 << 11)
|
||||
#define WIN_D_UPDATE (1 << 12)
|
||||
#define CURSOR_UPDATE (1 << 15)
|
||||
#define NC_HOST_TRIG (1 << 24)
|
||||
|
||||
@@ -74,15 +92,38 @@
|
||||
#define WINDOW_A_SELECT (1 << 4)
|
||||
#define WINDOW_B_SELECT (1 << 5)
|
||||
#define WINDOW_C_SELECT (1 << 6)
|
||||
#define WINDOW_D_SELECT (1 << 7)
|
||||
|
||||
#define DC_CMD_REG_ACT_CONTROL 0x043
|
||||
|
||||
// DC_D_WIN_DD window D instance of DC_WIN
|
||||
#define DC_D_WIN_DD_WIN_OPTIONS 0x80
|
||||
#define DC_D_WIN_DD_COLOR_DEPTH 0x83
|
||||
#define DC_D_WIN_DD_POSITION 0x84
|
||||
#define DC_D_WIN_DD_SIZE 0x85
|
||||
#define DC_D_WIN_DD_LINE_STRIDE 0x8A
|
||||
#define DC_D_WIN_DD_BLEND_LAYER_CONTROL 0x96
|
||||
#define DC_D_WIN_DD_BLEND_MATCH_SELECT 0x97
|
||||
#define DC_D_WIN_DD_BLEND_ALPHA_1BIT 0x99
|
||||
|
||||
// DC_D_WINBUF_DD window D instance of DC_WINBUF
|
||||
#define DC_D_WINBUF_DD_START_ADDR 0xC0
|
||||
#define DC_D_WINBUF_DD_ADDR_H_OFFSET 0xC6
|
||||
#define DC_D_WINBUF_DD_ADDR_V_OFFSET 0xC8
|
||||
#define DC_D_WINBUF_DD_START_ADDR_HI 0xCD
|
||||
#define DC_D_WINBUF_DD_MEMFETCH_CONTROL 0xEB
|
||||
|
||||
// DC_T_WIN_TD macro for using DD defines.
|
||||
#define _DC_T(reg) ((reg) + 0x80)
|
||||
|
||||
// DC_COM non-shadowed registers.
|
||||
#define DC_COM_CRC_CONTROL 0x300
|
||||
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
|
||||
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
|
||||
|
||||
#define DC_COM_DSC_TOP_CTL 0x33E
|
||||
|
||||
// DC_DISP shadowed registers.
|
||||
#define DC_DISP_DISP_WIN_OPTIONS 0x402
|
||||
#define HDMI_ENABLE (1 << 30)
|
||||
#define DSI_ENABLE (1 << 29)
|
||||
@@ -161,6 +202,32 @@
|
||||
#define DE_CONTROL_EARLY (3 << 2)
|
||||
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
|
||||
|
||||
// Cursor configuration registers.
|
||||
#define DC_DISP_CURSOR_FOREGROUND 0x43C
|
||||
#define DC_DISP_CURSOR_BACKGROUND 0x43D
|
||||
#define CURSOR_COLOR(r,g,b) (((r) & 0xFF) | (((g) & 0xFF) << 8) | (((b) & 0xFF) << 16))
|
||||
|
||||
#define DC_DISP_CURSOR_START_ADDR 0x43E
|
||||
#define CURSOR_CLIPPING(w) ((w) << 28)
|
||||
#define CURSOR_CLIP_WIN_A 1
|
||||
#define CURSOR_CLIP_WIN_B 2
|
||||
#define CURSOR_CLIP_WIN_C 3
|
||||
#define CURSOR_SIZE_32 (0 << 24)
|
||||
#define CURSOR_SIZE_64 (1 << 24)
|
||||
#define CURSOR_SIZE_128 (2 << 24)
|
||||
#define CURSOR_SIZE_256 (3 << 24)
|
||||
#define DC_DISP_CURSOR_POSITION 0x440
|
||||
#define DC_DISP_CURSOR_START_ADDR_HI 0x4EC
|
||||
#define DC_DISP_BLEND_CURSOR_CONTROL 0x4F1
|
||||
#define CURSOR_BLEND_2BIT (0 << 24)
|
||||
#define CURSOR_BLEND_R8G8B8A8 (1 << 24)
|
||||
#define CURSOR_BLEND_SRC_FACTOR(n) ((n) << 8)
|
||||
#define CURSOR_BLEND_DST_FACTOR(n) ((n) << 16)
|
||||
#define CURSOR_BLEND_ZRO 0
|
||||
#define CURSOR_BLEND_K1 1
|
||||
#define CURSOR_BLEND_NK1 2
|
||||
// End of cursor cfg regs.
|
||||
|
||||
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
|
||||
#define DC_DISP_SD_BL_PARAMETERS 0x4D7
|
||||
#define DC_DISP_SD_BL_CONTROL 0x4DC
|
||||
@@ -187,6 +254,13 @@
|
||||
#define CSC_ENABLE (1 << 18)
|
||||
#define WIN_ENABLE (1 << 30)
|
||||
|
||||
#define DC_WIN_BUFFER_CONTROL 0x702
|
||||
#define BUFFER_CONTROL_HOST 0
|
||||
#define BUFFER_CONTROL_VI 1
|
||||
#define BUFFER_CONTROL_EPP 2
|
||||
#define BUFFER_CONTROL_MPEGE 3
|
||||
#define BUFFER_CONTROL_SB2D 4
|
||||
|
||||
#define DC_WIN_COLOR_DEPTH 0x703
|
||||
#define WIN_COLOR_DEPTH_P1 0x0
|
||||
#define WIN_COLOR_DEPTH_P2 0x1
|
||||
@@ -211,8 +285,9 @@
|
||||
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
|
||||
#define WIN_COLOR_DEPTH_YUV422RA 0x19
|
||||
|
||||
#define DC_WIN_BUFFER_CONTROL 0x702
|
||||
#define DC_WIN_POSITION 0x704
|
||||
#define H_POSITION(x) (((x) & 0xFfff) << 0)
|
||||
#define V_POSITION(x) (((x) & 0x1fff) << 16)
|
||||
|
||||
#define DC_WIN_SIZE 0x705
|
||||
#define H_SIZE(x) (((x) & 0x1fff) << 0)
|
||||
@@ -234,6 +309,42 @@
|
||||
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
|
||||
#define DC_WIN_DV_CONTROL 0x70E
|
||||
|
||||
#define DC_WINBUF_BLEND_LAYER_CONTROL 0x716
|
||||
#define WIN_K1(x) (((x) & 0xff) << 8)
|
||||
#define WIN_K2(x) (((x) & 0xff) << 16)
|
||||
#define WIN_BLEND_ENABLE (0 << 24)
|
||||
#define WIN_BLEND_BYPASS (1 << 24)
|
||||
|
||||
#define DC_WINBUF_BLEND_MATCH_SELECT 0x717
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ZERO (0 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ONE (1 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 (2 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_DST (3 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_NEG_K1_TIMES_DST (4 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_SRC (5 << 0)
|
||||
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ZERO (0 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ONE (1 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1 (2 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K2 (3 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1_TIMES_DST (4 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_DST (5 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_SRC (6 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1 (7 << 4)
|
||||
|
||||
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_ZERO (0 << 8)
|
||||
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K1 (1 << 8)
|
||||
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K2 (2 << 8)
|
||||
|
||||
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ZERO (0 << 12)
|
||||
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ONE (1 << 12)
|
||||
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_NEG_K1_TIMES_SRC (2 << 12)
|
||||
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_K2 (3 << 12)
|
||||
|
||||
#define DC_WINBUF_BLEND_ALPHA_1BIT 0x719
|
||||
#define WIN_ALPHA_1BIT_WEIGHT0(x) (((x) & 0xff) << 0)
|
||||
#define WIN_ALPHA_1BIT_WEIGHT1(x) (((x) & 0xff) << 8)
|
||||
|
||||
/*! The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
|
||||
#define DC_WINBUF_START_ADDR 0x800
|
||||
#define DC_WINBUF_ADDR_H_OFFSET 0x806
|
||||
@@ -336,6 +447,7 @@
|
||||
|
||||
#define DSI_PAD_CONTROL_CD 0x4C
|
||||
#define DSI_VIDEO_MODE_CONTROL 0x4E
|
||||
#define DSI_CMD_PKT_VID_ENABLE 1
|
||||
|
||||
#define DSI_PAD_CONTROL_1 0x4F
|
||||
#define DSI_PAD_CONTROL_2 0x50
|
||||
@@ -349,7 +461,57 @@
|
||||
#define DSI_PAD_CONTROL_4 0x52
|
||||
#define DSI_INIT_SEQ_DATA_15 0x5F
|
||||
|
||||
#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 0x60
|
||||
/*! MIPI registers. */
|
||||
#define MIPI_CAL_MIPI_CAL_CTRL (0x00 / 0x4)
|
||||
#define MIPI_CAL_CIL_MIPI_CAL_STATUS (0x08 / 0x4)
|
||||
#define MIPI_CAL_CILA_MIPI_CAL_CONFIG (0x14 / 0x4)
|
||||
#define MIPI_CAL_CILB_MIPI_CAL_CONFIG (0x18 / 0x4)
|
||||
#define MIPI_CAL_CILC_MIPI_CAL_CONFIG (0x1C / 0x4)
|
||||
#define MIPI_CAL_CILD_MIPI_CAL_CONFIG (0x20 / 0x4)
|
||||
#define MIPI_CAL_CILE_MIPI_CAL_CONFIG (0x24 / 0x4)
|
||||
#define MIPI_CAL_CILF_MIPI_CAL_CONFIG (0x28 / 0x4)
|
||||
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG (0x38 / 0x4)
|
||||
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG (0x3C / 0x4)
|
||||
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG (0x40 / 0x4)
|
||||
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG (0x44 / 0x4)
|
||||
#define MIPI_CAL_MIPI_BIAS_PAD_CFG0 (0x58 / 0x4)
|
||||
#define MIPI_CAL_MIPI_BIAS_PAD_CFG1 (0x5C / 0x4)
|
||||
#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 (0x60 / 0x4)
|
||||
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2 (0x64 / 0x4)
|
||||
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2 (0x68 / 0x4)
|
||||
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2 (0x70 / 0x4)
|
||||
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG_2 (0x74 / 0x4)
|
||||
|
||||
/*! MIPI CMDs. */
|
||||
#define MIPI_DSI_DCS_SHORT_WRITE 0x05
|
||||
#define MIPI_DSI_DCS_READ 0x06
|
||||
#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15
|
||||
#define MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE 0x37
|
||||
#define MIPI_DSI_DCS_LONG_WRITE 0x39
|
||||
|
||||
/*! MIPI DCS CMDs. */
|
||||
#define MIPI_DCS_GET_DISPLAY_ID 0x04
|
||||
#define MIPI_DCS_ENTER_SLEEP_MODE 0x10
|
||||
#define MIPI_DCS_EXIT_SLEEP_MODE 0x11
|
||||
#define MIPI_DCS_SET_DISPLAY_ON 0x29
|
||||
|
||||
/* Switch Panels:
|
||||
* [10] 81 [26]: JDI LPM062M326A
|
||||
* [10] 96 [09]: JDI LAM062M109A
|
||||
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
|
||||
* [20] XX [10]: InnoLux P062CCA-AZ2 [UNCONFIRMED ID]
|
||||
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
|
||||
* [30] XX [10]: AUO A062TAN02 (59.06A33.002) [UNCONFIRMED ID]
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
PANEL_JDI_LPM062M = 0x10,
|
||||
PANEL_INL_P062CCA_AZ1 = 0x0F20,
|
||||
PANEL_AUO_A062TAN01 = 0x0F30,
|
||||
PANEL_INL_P062CCA_AZ2 = 0x1020,
|
||||
PANEL_AUO_A062TAN02 = 0x1030
|
||||
};
|
||||
|
||||
void display_init();
|
||||
void display_backlight_pwm_init();
|
||||
@@ -364,5 +526,8 @@ void display_backlight_brightness(u32 brightness, u32 step_delay);
|
||||
|
||||
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
|
||||
u32 *display_init_framebuffer();
|
||||
void display_init_cursor(void *crs_fb, u32 size);
|
||||
void display_set_pos_cursor(u32 x, u32 y);
|
||||
void display_deinit_cursor();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-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,
|
||||
@@ -15,16 +15,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//Clock config.
|
||||
static const cfg_op_t _display_config_1[4] = {
|
||||
{0x4E, 0x40000000}, //CLK_RST_CONTROLLER_CLK_SOURCE_DISP1
|
||||
{0x34, 0x4830A001}, //CLK_RST_CONTROLLER_PLLD_BASE
|
||||
{0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1
|
||||
{0x37, 0x2D0AAA} //CLK_RST_CONTROLLER_PLLD_MISC
|
||||
};
|
||||
|
||||
//Display A config.
|
||||
static const cfg_op_t _display_config_2[94] = {
|
||||
static const cfg_op_t _display_dc_setup_win_config[94] = {
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
@@ -128,7 +120,7 @@ static const cfg_op_t _display_config_2[94] = {
|
||||
};
|
||||
|
||||
//DSI Init config.
|
||||
static const cfg_op_t _display_config_3[61] = {
|
||||
static const cfg_op_t _display_dsi_init_config[61] = {
|
||||
{DSI_WR_DATA, 0},
|
||||
{DSI_INT_ENABLE, 0},
|
||||
{DSI_INT_STATUS, 0},
|
||||
@@ -192,14 +184,14 @@ static const cfg_op_t _display_config_3[61] = {
|
||||
{DSI_INIT_SEQ_CONTROL, 0}
|
||||
};
|
||||
|
||||
//DSI config (if ver == 0x10).
|
||||
static const cfg_op_t _display_config_4[43] = {
|
||||
{DSI_WR_DATA, 0x439},
|
||||
{DSI_WR_DATA, 0x9483FFB9},
|
||||
//DSI panel config.
|
||||
static const cfg_op_t _display_init_config_jdi[43] = {
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xBD15},
|
||||
{DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x0BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x1939},
|
||||
{DSI_WR_DATA, 0x1939}, // MIPI_DSI_DCS_LONG_WRITE: 25 bytes.
|
||||
{DSI_WR_DATA, 0xAAAAAAD8},
|
||||
{DSI_WR_DATA, 0xAAAAAAEB},
|
||||
{DSI_WR_DATA, 0xAAEBAAAA},
|
||||
@@ -208,9 +200,9 @@ static const cfg_op_t _display_config_4[43] = {
|
||||
{DSI_WR_DATA, 0xAAEBAAAA},
|
||||
{DSI_WR_DATA, 0xAA},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x1BD15},
|
||||
{DSI_WR_DATA, 0x01BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x1BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2739},
|
||||
{DSI_WR_DATA, 0x2739}, // MIPI_DSI_DCS_LONG_WRITE: 39 bytes.
|
||||
{DSI_WR_DATA, 0xFFFFFFD8},
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
@@ -222,25 +214,25 @@ static const cfg_op_t _display_config_4[43] = {
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
{DSI_WR_DATA, 0xFFFFFF},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2BD15},
|
||||
{DSI_WR_DATA, 0x02BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x2BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xF39},
|
||||
{DSI_WR_DATA, 0xF39}, // MIPI_DSI_DCS_LONG_WRITE: 15 bytes.
|
||||
{DSI_WR_DATA, 0xFFFFFFD8},
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
{DSI_WR_DATA, 0xFFFFFF},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xBD15},
|
||||
{DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x0BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x6D915},
|
||||
{DSI_WR_DATA, 0x06D915}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x6D9.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x439},
|
||||
{DSI_WR_DATA, 0xB9},
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x000000B9}, // Disable extension cmd.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST}
|
||||
};
|
||||
|
||||
//DSI config.
|
||||
static const cfg_op_t _display_config_5[21] = {
|
||||
//DSI packet config.
|
||||
static const cfg_op_t _display_dsi_packet_config[21] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PHY_TIMING_0, 0x6070601},
|
||||
{DSI_PHY_TIMING_1, 0x40A0E05},
|
||||
@@ -264,15 +256,8 @@ static const cfg_op_t _display_config_5[21] = {
|
||||
{DSI_HOST_CONTROL, 0},
|
||||
};
|
||||
|
||||
//Clock config.
|
||||
static const cfg_op_t _display_config_6[3] = {
|
||||
{0x34, 0x4810C001}, //CLK_RST_CONTROLLER_PLLD_BASE
|
||||
{0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1
|
||||
{0x37, 0x2DFC00} //CLK_RST_CONTROLLER_PLLD_MISC
|
||||
};
|
||||
|
||||
//DSI config.
|
||||
static const cfg_op_t _display_config_7[10] = {
|
||||
//DSI mode config.
|
||||
static const cfg_op_t _display_dsi_mode_config[10] = {
|
||||
{DSI_TRIGGER, 0},
|
||||
{DSI_CONTROL, 0},
|
||||
{DSI_SOL_DELAY, 6},
|
||||
@@ -286,17 +271,17 @@ static const cfg_op_t _display_config_7[10] = {
|
||||
};
|
||||
|
||||
//MIPI CAL config.
|
||||
static const cfg_op_t _display_config_8[6] = {
|
||||
{0x18, 0}, // MIPI_CAL_MIPI_BIAS_PAD_CFG2
|
||||
{0x02, 0xF3F10000}, // MIPI_CAL_CIL_MIPI_CAL_STATUS
|
||||
{0x16, 0}, // MIPI_CAL_MIPI_BIAS_PAD_CFG0
|
||||
{0x18, 0}, // MIPI_CAL_MIPI_BIAS_PAD_CFG2
|
||||
{0x18, 0x10010}, // MIPI_CAL_MIPI_BIAS_PAD_CFG2
|
||||
{0x17, 0x300} // MIPI_CAL_MIPI_BIAS_PAD_CFG1
|
||||
static const cfg_op_t _display_mipi_pad_cal_config[6] = {
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
|
||||
{MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0x300}
|
||||
};
|
||||
|
||||
//DSI config.
|
||||
static const cfg_op_t _display_config_9[4] = {
|
||||
static const cfg_op_t _display_dsi_pad_cal_config[4] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PAD_CONTROL_2, 0},
|
||||
{DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)},
|
||||
@@ -304,27 +289,27 @@ static const cfg_op_t _display_config_9[4] = {
|
||||
};
|
||||
|
||||
//MIPI CAL config.
|
||||
static const cfg_op_t _display_config_10[16] = {
|
||||
{0x0E, 0x200200}, // MIPI_CAL_DSIA_MIPI_CAL_CONFIG
|
||||
{0x0F, 0x200200}, // MIPI_CAL_DSIB_MIPI_CAL_CONFIG
|
||||
{0x19, 0x200002}, // MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2
|
||||
{0x1A, 0x200002}, // MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2
|
||||
{0x05, 0}, // MIPI_CAL_CILA_MIPI_CAL_CONFIG
|
||||
{0x06, 0}, // MIPI_CAL_CILB_MIPI_CAL_CONFIG
|
||||
{0x07, 0}, // MIPI_CAL_CILC_MIPI_CAL_CONFIG
|
||||
{0x08, 0}, // MIPI_CAL_CILD_MIPI_CAL_CONFIG
|
||||
{0x09, 0}, // MIPI_CAL_CILE_MIPI_CAL_CONFIG
|
||||
{0x0A, 0}, // MIPI_CAL_CILF_MIPI_CAL_CONFIG
|
||||
{0x10, 0}, // MIPI_CAL_DSIC_MIPI_CAL_CONFIG
|
||||
{0x11, 0}, // MIPI_CAL_DSID_MIPI_CAL_CONFIG
|
||||
{0x1A, 0}, // MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2
|
||||
{0x1C, 0}, // MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2
|
||||
{0x1D, 0}, // MIPI_CAL_DSID_MIPI_CAL_CONFIG_2
|
||||
{0, 0x2A000001} // MIPI_CAL_DSIA_MIPI_CAL_CONFIG
|
||||
static const cfg_op_t _display_mipi_apply_dsi_cal_config[16] = {
|
||||
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200},
|
||||
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002},
|
||||
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILD_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILE_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILF_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_DSID_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0},
|
||||
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0},
|
||||
{MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0},
|
||||
{MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001}
|
||||
};
|
||||
|
||||
//Display A config.
|
||||
static const cfg_op_t _display_config_11[113] = {
|
||||
static const cfg_op_t _display_video_disp_controller_enable_config[113] = {
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
@@ -449,7 +434,7 @@ static const cfg_op_t _display_config_11[113] = {
|
||||
};
|
||||
|
||||
////Display A config.
|
||||
static const cfg_op_t _display_config_12[17] = {
|
||||
static const cfg_op_t _display_video_disp_controller_disable_config[17] = {
|
||||
{DC_DISP_FRONT_PORCH, 0xA0088},
|
||||
{DC_CMD_INT_MASK, 0},
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
@@ -470,7 +455,7 @@ static const cfg_op_t _display_config_12[17] = {
|
||||
};
|
||||
|
||||
//DSI config.
|
||||
static const cfg_op_t _display_config_13[16] = {
|
||||
static const cfg_op_t _display_dsi_timing_deinit_config[16] = {
|
||||
{DSI_POWER_CONTROL, 0},
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PHY_TIMING_0, 0x6070601},
|
||||
@@ -490,11 +475,11 @@ static const cfg_op_t _display_config_13[16] = {
|
||||
};
|
||||
|
||||
//DSI config (if ver == 0x10).
|
||||
static const cfg_op_t _display_config_14[22] = {
|
||||
{DSI_WR_DATA, 0x439},
|
||||
{DSI_WR_DATA, 0x9483FFB9},
|
||||
static const cfg_op_t _display_deinit_config_jdi[22] = {
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2139},
|
||||
{DSI_WR_DATA, 0x2139}, // MIPI_DSI_DCS_LONG_WRITE: 33 bytes.
|
||||
{DSI_WR_DATA, 0x191919D5},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
@@ -505,60 +490,107 @@ static const cfg_op_t _display_config_14[22] = {
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xB39},
|
||||
{DSI_WR_DATA, 0x4F0F41B1},
|
||||
{DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
|
||||
{DSI_WR_DATA, 0x4F0F41B1}, // Set Power control.
|
||||
{DSI_WR_DATA, 0xF179A433},
|
||||
{DSI_WR_DATA, 0x2D81},
|
||||
{DSI_WR_DATA, 0x002D81},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x439},
|
||||
{DSI_WR_DATA, 0xB9},
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x000000B9}, // Disable extension cmd.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST}
|
||||
};
|
||||
|
||||
static const cfg_op_t _display_deinit_config_auo[37] = {
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes.
|
||||
{DSI_WR_DATA, 0x191919D5},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes.
|
||||
{DSI_WR_DATA, 0x191919D6},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
|
||||
{DSI_WR_DATA, 0x711148B1}, // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
|
||||
// Set Power control. (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG).
|
||||
{DSI_WR_DATA, 0x71143209},
|
||||
{DSI_WR_DATA, 0x114D31}, // Set Power control. (Unknown).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x000000B9}, // Disable extension cmd.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST}
|
||||
};
|
||||
|
||||
static const cfg_op_t _display_init_config_invert[3] = {
|
||||
{DSI_WR_DATA, 0x239},
|
||||
{DSI_WR_DATA, 0x02C1}, // INV_EN.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
};
|
||||
|
||||
//Display A config.
|
||||
static const cfg_op_t cfg_display_one_color[8] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} //DISPLAY_CTRL_MODE: continuous display.
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display.
|
||||
};
|
||||
|
||||
//Display A config.
|
||||
static const cfg_op_t cfg_display_framebuffer[32] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //T_A8R8G8B8 //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_POSITION, 0}, //(0,0)
|
||||
{DC_WIN_H_INITIAL_DDA, 0},
|
||||
{DC_WIN_V_INITIAL_DDA, 0},
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, //Pre-scaled size: 1280x2880 bytes.
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)},
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, //Window size: 1280 vertical lines x 720 horizontal pixels.
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, 0},
|
||||
{DC_WINBUF_SURFACE_KIND, 0}, //Regular surface.
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)},
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
|
||||
{DC_WINBUF_SURFACE_KIND, PITCH},
|
||||
{DC_WINBUF_START_ADDR, IPL_FB_ADDRESS}, // Framebuffer address.
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0},
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 0},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE}, //Enable window AD.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request.
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
@@ -219,7 +219,7 @@ void gfx_putc(char c)
|
||||
else if (c == '\n')
|
||||
{
|
||||
gfx_con.x = 0;
|
||||
gfx_con.y +=16;
|
||||
gfx_con.y += 16;
|
||||
if (gfx_con.y > gfx_ctxt.height - 16)
|
||||
gfx_con.y = 0;
|
||||
}
|
||||
|
||||
@@ -24,31 +24,37 @@
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
|
||||
#include "../gfx/gfx.h"
|
||||
#define DPRINTF(...)
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern void *sd_file_read(const char *path, u32 *fsize);
|
||||
extern bool is_ipl_updated(void *buf, char *path, bool force);
|
||||
|
||||
// FSS0 Magic and Meta header offset.
|
||||
#define FSS0_MAGIC 0x30535346
|
||||
#define FSS0_META_OFFSET 0x4
|
||||
|
||||
// FSS0 Content Types.
|
||||
#define CNT_TYPE_FSP 0
|
||||
#define CNT_TYPE_EXO 1
|
||||
#define CNT_TYPE_WBT 2
|
||||
#define CNT_TYPE_RBT 3
|
||||
#define CNT_TYPE_SP1 4
|
||||
#define CNT_TYPE_SP2 5
|
||||
#define CNT_TYPE_KIP 6
|
||||
#define CNT_TYPE_EXO 1 // Exosphere (Secure Monitor).
|
||||
#define CNT_TYPE_WBT 2 // Warmboot (SC7Exit fw).
|
||||
#define CNT_TYPE_RBT 3 // Rebootstub (Warmboot based reboot fw).
|
||||
#define CNT_TYPE_SP1 4 // Sept Primary (TSEC and Sept Secondary loader).
|
||||
#define CNT_TYPE_SP2 5 // Sept Secondary (Acts as pkg11 and derives keys).
|
||||
#define CNT_TYPE_KIP 6 // KIP1 (Used for replacement or addition).
|
||||
#define CNT_TYPE_BMP 7
|
||||
#define CNT_TYPE_EMC 8
|
||||
#define CNT_TYPE_KLD 9
|
||||
#define CNT_TYPE_KRN 10
|
||||
#define CNT_TYPE_KLD 9 // Kernel Loader.
|
||||
#define CNT_TYPE_KRN 10 // Kernel.
|
||||
|
||||
// FSS0 Content Flags.
|
||||
#define CNT_FLAG0_EXPERIMENTAL (1 << 0)
|
||||
|
||||
typedef struct _fss_t
|
||||
// FSS0 Meta Header.
|
||||
typedef struct _fss_meta_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 size;
|
||||
@@ -58,8 +64,9 @@ typedef struct _fss_t
|
||||
u32 hos_ver;
|
||||
u32 version;
|
||||
u32 git_rev;
|
||||
} fss_t;
|
||||
} fss_meta_t;
|
||||
|
||||
// FSS0 Content Header.
|
||||
typedef struct _fss_content_t
|
||||
{
|
||||
u32 offset;
|
||||
@@ -121,12 +128,15 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
|
||||
return 0;
|
||||
|
||||
void *fss = malloc(f_size(&fp));
|
||||
// Read header.
|
||||
f_read(&fp, fss, 0x400, NULL);
|
||||
|
||||
u32 fss_entry = *(u32 *)(fss + 4);
|
||||
fss_t *fss_meta = (fss_t *)(fss + fss_entry);
|
||||
// Read first 1024 bytes of the fss file.
|
||||
f_read(&fp, fss, 1024, NULL);
|
||||
|
||||
// Get FSS0 Meta header offset.
|
||||
u32 fss_meta_addr = *(u32 *)(fss + FSS0_META_OFFSET);
|
||||
fss_meta_t *fss_meta = (fss_meta_t *)(fss + fss_meta_addr);
|
||||
|
||||
// Check if valid FSS0 and parse it.
|
||||
if (fss_meta->magic == FSS0_MAGIC)
|
||||
{
|
||||
gfx_printf("Found FSS0, Atmosphere %d.%d.%d-%08x\n"
|
||||
@@ -141,20 +151,25 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
|
||||
ctxt->fss0_hosver = fss_meta->hos_ver;
|
||||
}
|
||||
|
||||
// Parse FSS0 contents.
|
||||
fss_content_t *curr_fss_cnt = (fss_content_t *)(fss + fss_meta->cnt_off);
|
||||
void *content;
|
||||
for (u32 i = 0; i < fss_meta->cnt_count; i++)
|
||||
{
|
||||
content = (void *)(fss + curr_fss_cnt[i].offset);
|
||||
|
||||
// Check if offset is inside limits.
|
||||
if ((curr_fss_cnt[i].offset + curr_fss_cnt[i].size) > fss_meta->size)
|
||||
continue;
|
||||
|
||||
// If content is experimental and experimental flag is not enabled, skip it.
|
||||
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_enable_experimental)
|
||||
continue;
|
||||
|
||||
// Load content to launch context.
|
||||
// Parse content.
|
||||
if (!sept_ctxt)
|
||||
{
|
||||
// Prepare content context.
|
||||
switch (curr_fss_cnt[i].type)
|
||||
{
|
||||
case CNT_TYPE_KIP:
|
||||
@@ -176,16 +191,20 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load content to launch context.
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, content, curr_fss_cnt[i].size, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load content to launch context.
|
||||
// Load sept content directly to launch context.
|
||||
switch (curr_fss_cnt[i].type)
|
||||
{
|
||||
case CNT_TYPE_SP1:
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, sept_ctxt->sept_primary, curr_fss_cnt[i].size, NULL);
|
||||
continue;
|
||||
break;
|
||||
case CNT_TYPE_SP2:
|
||||
if (!memcmp(curr_fss_cnt[i].name, (sept_ctxt->kb < KB_FIRMWARE_VERSION_810) ? "septsecondary00" : "septsecondary01", 15))
|
||||
{
|
||||
@@ -194,14 +213,11 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
|
||||
sept_used = 1;
|
||||
goto out;
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
||||
f_read(&fp, content, curr_fss_cnt[i].size, NULL);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018 Ced2911
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -40,15 +40,13 @@
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/util.h"
|
||||
#include "../gfx/gfx.h"
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern void sd_unmount();
|
||||
extern bool sd_mount();
|
||||
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
|
||||
@@ -185,7 +183,114 @@ void _sysctr0_reset()
|
||||
SYSCTR0(SYSCTR0_COUNTERID11) = 0;
|
||||
}
|
||||
|
||||
int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
|
||||
void hos_eks_get()
|
||||
{
|
||||
// Check if EKS already found and parsed.
|
||||
if (!h_cfg.eks)
|
||||
{
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
|
||||
// Read EKS blob.
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
|
||||
// Decrypt EKS blob.
|
||||
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x10);
|
||||
se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Check if valid and for this unit.
|
||||
if (eks->enabled &&
|
||||
eks->magic == HOS_EKS_MAGIC &&
|
||||
eks->magic2 == HOS_EKS_MAGIC &&
|
||||
eks->sbk_low[0] == FUSE(FUSE_PRIVATE_KEY0) &&
|
||||
eks->sbk_low[1] == FUSE(FUSE_PRIVATE_KEY1))
|
||||
{
|
||||
h_cfg.eks = eks;
|
||||
return;
|
||||
}
|
||||
|
||||
free(mbr);
|
||||
}
|
||||
}
|
||||
|
||||
void hos_eks_save(u32 kb)
|
||||
{
|
||||
if (kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
// Only 6 Master keys for now.
|
||||
u8 key_idx = kb - KB_FIRMWARE_VERSION_700;
|
||||
if (key_idx > 5)
|
||||
return;
|
||||
|
||||
if (!h_cfg.eks)
|
||||
h_cfg.eks = calloc(512 , 1);
|
||||
|
||||
// If matching blob doesn't exist, create it.
|
||||
if (!(h_cfg.eks->enabled & (1 << key_idx)))
|
||||
{
|
||||
// Get keys.
|
||||
u8 *keys = (u8 *)calloc(0x1000, 1);
|
||||
se_get_aes_keys(keys + 0x800, keys, 0x10);
|
||||
|
||||
// Set magic and personalized info.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
h_cfg.eks->magic2 = HOS_EKS_MAGIC;
|
||||
h_cfg.eks->enabled |= 1 << key_idx;
|
||||
h_cfg.eks->sbk_low[0] = FUSE(FUSE_PRIVATE_KEY0);
|
||||
h_cfg.eks->sbk_low[1] = FUSE(FUSE_PRIVATE_KEY1);
|
||||
|
||||
// Copy new keys.
|
||||
memcpy(h_cfg.eks->keys[key_idx].dkg, keys + 10 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].dkk, keys + 15 * 0x10, 0x10);
|
||||
|
||||
// Encrypt EKS.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Write EKS to SD.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
|
||||
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
|
||||
|
||||
free(eks);
|
||||
free(mbr);
|
||||
free(keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hos_eks_clear(u32 kb)
|
||||
{
|
||||
if (h_cfg.eks && kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
// Check if Current Master key is enabled.
|
||||
u8 key_idx = kb - KB_FIRMWARE_VERSION_700;
|
||||
if (h_cfg.eks->enabled & (1 << key_idx))
|
||||
{
|
||||
// Disable current Master key version.
|
||||
h_cfg.eks->enabled &= ~(1 << key_idx);
|
||||
|
||||
// Encrypt EKS.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
|
||||
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
|
||||
|
||||
// Write EKS to SD.
|
||||
u8 *mbr = calloc(512 , 1);
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t));
|
||||
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
|
||||
|
||||
free(eks);
|
||||
free(mbr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
|
||||
{
|
||||
u8 tmp[0x20];
|
||||
u32 retries = 0;
|
||||
@@ -228,7 +333,27 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
|
||||
}
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
// Use HOS EKS if it exists.
|
||||
u8 key_idx = kb - KB_FIRMWARE_VERSION_700;
|
||||
if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx)))
|
||||
{
|
||||
// Set Device keygen key to slot 10.
|
||||
se_aes_key_set(10, h_cfg.eks->keys[key_idx].dkg, 0x10);
|
||||
// Set Master key to slot 12.
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10);
|
||||
// Set FW Device key key to slot 13.
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10);
|
||||
// Set Device key to slot 15.
|
||||
se_aes_key_set(15, h_cfg.eks->keys[key_idx].dkk, 0x10);
|
||||
|
||||
// Lock FDK.
|
||||
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
}
|
||||
|
||||
se_aes_key_clear(8);
|
||||
se_aes_unwrap_key(8, 12, package2_keyseed);
|
||||
}
|
||||
else if (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
// Set TSEC key.
|
||||
@@ -346,13 +471,13 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
|
||||
|
||||
// Read package1.
|
||||
ctxt->pkg1 = (void *)malloc(0x40000);
|
||||
emummc_storage_set_mmc_partition(&storage, 1);
|
||||
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
|
||||
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1);
|
||||
if (!ctxt->pkg1_id)
|
||||
{
|
||||
_hos_crit_error("Unknown pkg1 version.");
|
||||
EHPRINTFARGS("%sNot yet supported HOS version!",
|
||||
EHPRINTFARGS("%sNot yet supported HOS version!",
|
||||
(emu_cfg.enabled && !h_cfg.emummc_force_disable) ? "Is emuMMC corrupt?\nOr " : "");
|
||||
goto out;
|
||||
}
|
||||
@@ -387,7 +512,7 @@ static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
emummc_storage_set_mmc_partition(&storage, 0);
|
||||
emummc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
// Parse eMMC GPT.
|
||||
LIST_INIT(gpt);
|
||||
@@ -436,6 +561,37 @@ static void _free_launch_components(launch_ctxt_t *ctxt)
|
||||
free(ctxt->kip1_patches);
|
||||
}
|
||||
|
||||
static bool _get_fs_exfat_compatible(link_t *info)
|
||||
{
|
||||
u32 fs_idx;
|
||||
u32 fs_ids_cnt;
|
||||
u32 sha_buf[32 / sizeof(u32)];
|
||||
kip1_id_t *kip_ids;
|
||||
|
||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
|
||||
{
|
||||
if (strncmp((const char*)ki->kip1->name, "FS", 2))
|
||||
continue;
|
||||
|
||||
if (!se_calc_sha256(sha_buf, ki->kip1, ki->size))
|
||||
break;
|
||||
|
||||
pkg2_get_ids(&kip_ids, &fs_ids_cnt);
|
||||
|
||||
for (fs_idx = 0; fs_idx < fs_ids_cnt; fs_idx++)
|
||||
if (!memcmp(sha_buf, kip_ids[fs_idx].hash, 8))
|
||||
break;
|
||||
|
||||
// Return false if FAT32 only.
|
||||
if (fs_ids_cnt <= fs_idx && !(fs_idx & 1))
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int hos_launch(ini_sec_t *cfg)
|
||||
{
|
||||
minerva_change_freq(FREQ_1600);
|
||||
@@ -478,17 +634,26 @@ int hos_launch(ini_sec_t *cfg)
|
||||
ctxt.atmosphere = true; // Set atmosphere patching in case of Stock emuMMC and no fss0.
|
||||
config_kip1patch(&ctxt, "emummc");
|
||||
}
|
||||
else if (!emu_cfg.enabled && ctxt.emummc_forced)
|
||||
{
|
||||
_hos_crit_error("emuMMC is forced but not enabled!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if fuses lower than 4.0.0 or 9.0.0 and if yes apply NO Gamecard patch.
|
||||
// Additionally check if running emuMMC and disable GC if v3 fuses are burnt and HOS is <= 8.1.0.
|
||||
if ((h_cfg.autonogc &&
|
||||
((!(fuse_read_odm(7) & ~0xF) && (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_400)) || // LAFW v2.
|
||||
(!(fuse_read_odm(7) & ~0x3FF) && (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_900)))) // LAFW v3.
|
||||
|| ((emu_cfg.enabled && !h_cfg.emummc_force_disable) &&
|
||||
((fuse_read_odm(7) & 0x400) && (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_810))))
|
||||
config_kip1patch(&ctxt, "nogc");
|
||||
if (!ctxt.stock)
|
||||
{
|
||||
u32 fuses = fuse_read_odm(7);
|
||||
if ((h_cfg.autonogc &&
|
||||
((!(fuses & ~0xF) && (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_400)) || // LAFW v2.
|
||||
(!(fuses & ~0x3FF) && (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_900)))) // LAFW v3.
|
||||
|| ((emu_cfg.enabled && !h_cfg.emummc_force_disable) &&
|
||||
((fuses & 0x400) && (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_810))))
|
||||
config_kip1patch(&ctxt, "nogc");
|
||||
}
|
||||
|
||||
gfx_printf("Loaded pkg1 & keyblob\n");
|
||||
gfx_printf("Loaded config, pkg1 and keyblob\n");
|
||||
|
||||
// Generate keys.
|
||||
if (!h_cfg.se_keygen_done)
|
||||
@@ -504,7 +669,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!keygen(ctxt.keyblob, ctxt.pkg1_id->kb, &tsec_ctxt, &ctxt))
|
||||
if (!hos_keygen(ctxt.keyblob, ctxt.pkg1_id->kb, &tsec_ctxt, &ctxt))
|
||||
return 0;
|
||||
gfx_printf("Generated keys\n");
|
||||
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600)
|
||||
@@ -556,7 +721,7 @@ int hos_launch(ini_sec_t *cfg)
|
||||
{
|
||||
// Else we patch it to allow for an unsigned package2 and patched kernel.
|
||||
patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset;
|
||||
gfx_printf("%kPatching Security Monitor%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
gfx_printf("%kPatching Secure Monitor%k\n", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++)
|
||||
*(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val;
|
||||
}
|
||||
@@ -576,9 +741,16 @@ int hos_launch(ini_sec_t *cfg)
|
||||
{
|
||||
_hos_crit_error("Pkg2 decryption failed!");
|
||||
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700)
|
||||
{
|
||||
EPRINTF("Is Sept updated?");
|
||||
|
||||
// Clear EKS slot, in case something went wrong with sept keygen.
|
||||
hos_eks_clear(ctxt.pkg1_id->kb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700)
|
||||
hos_eks_save(ctxt.pkg1_id->kb); // Save EKS slot if it doesn't exist.
|
||||
|
||||
LIST_INIT(kip1_info);
|
||||
if (!pkg2_parse_kips(&kip1_info, pkg2_hdr, &ctxt.new_pkg2))
|
||||
@@ -643,6 +815,15 @@ int hos_launch(ini_sec_t *cfg)
|
||||
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
|
||||
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
|
||||
|
||||
// Check if FS is compatible with exFAT.
|
||||
if (!ctxt.stock && sd_fs.fs_type == FS_EXFAT && !_get_fs_exfat_compatible(&kip1_info))
|
||||
{
|
||||
_hos_crit_error("SD Card is exFAT and the installed\nFS only supports FAT32!");
|
||||
|
||||
_free_launch_components(&ctxt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Patch kip1s in memory if needed.
|
||||
const char* unappliedPatch = pkg2_patch_kips(&kip1_info, ctxt.kip1_patches);
|
||||
if (unappliedPatch != NULL)
|
||||
@@ -739,9 +920,6 @@ int hos_launch(ini_sec_t *cfg)
|
||||
secmon_mb->in = bootStateDramPkg2;
|
||||
secmon_mb->out = 0;
|
||||
|
||||
// Free allocated memory.
|
||||
_free_launch_components(&ctxt);
|
||||
|
||||
// Disable display. This must be executed before secmon to provide support for all fw versions.
|
||||
display_end();
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "../config/ini.h"
|
||||
#include "../sec/tsec.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define KB_FIRMWARE_VERSION_100_200 0
|
||||
#define KB_FIRMWARE_VERSION_300 1
|
||||
#define KB_FIRMWARE_VERSION_301 2
|
||||
@@ -38,6 +40,35 @@
|
||||
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_910
|
||||
|
||||
#define HOS_PKG11_MAGIC 0x31314B50
|
||||
#define HOS_EKS_MAGIC 0x30534B45
|
||||
|
||||
typedef struct _exo_ctxt_t
|
||||
{
|
||||
bool no_user_exceptions;
|
||||
bool user_pmu;
|
||||
bool *cal0_blank;
|
||||
bool *cal0_allow_writes_sys;
|
||||
} exo_ctxt_t;
|
||||
|
||||
typedef struct _hos_eks_keys_t
|
||||
{
|
||||
u8 dkg[0x10];
|
||||
u8 mkk[0x10];
|
||||
u8 fdk[0x10];
|
||||
u8 dkk[0x10];
|
||||
} hos_eks_keys_t;
|
||||
|
||||
typedef struct _hos_eks_mbr_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 enabled;
|
||||
u32 sbk_low[2];
|
||||
hos_eks_keys_t keys[6];
|
||||
u32 magic2;
|
||||
u32 rsvd2[3];
|
||||
} hos_eks_mbr_t;
|
||||
|
||||
static_assert(sizeof(hos_eks_mbr_t) < 424, "HOS EKS storage bigger than MBR!");
|
||||
|
||||
typedef struct _launch_ctxt_t
|
||||
{
|
||||
@@ -66,10 +97,10 @@ typedef struct _launch_ctxt_t
|
||||
bool debugmode;
|
||||
bool stock;
|
||||
bool atmosphere;
|
||||
bool exo_no_user_exceptions;
|
||||
bool exo_user_pmu;
|
||||
bool fss0_enable_experimental;
|
||||
bool emuMMC;
|
||||
bool emummc_forced;
|
||||
|
||||
exo_ctxt_t exo_cfg;
|
||||
|
||||
ini_sec_t *cfg;
|
||||
} launch_ctxt_t;
|
||||
@@ -80,7 +111,10 @@ typedef struct _merge_kip_t
|
||||
link_t link;
|
||||
} merge_kip_t;
|
||||
|
||||
int hos_launch(ini_sec_t *cfg);
|
||||
int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
|
||||
void hos_eks_get();
|
||||
void hos_eks_save(u32 kb);
|
||||
void hos_eks_clear(u32 kb);
|
||||
int hos_launch(ini_sec_t *cfg);
|
||||
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "fss.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../utils/dirlist.h"
|
||||
|
||||
#include "../gfx/gfx.h"
|
||||
@@ -29,8 +30,6 @@
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
|
||||
extern void *sd_file_read(const char *path, u32 *fsize);
|
||||
|
||||
static int _config_warmboot(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
ctxt->warmboot = sd_file_read(value, &ctxt->warmboot_size);
|
||||
@@ -181,6 +180,16 @@ static int _config_stock(launch_ctxt_t *ctxt, const char *value)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_emummc_forced(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Forced emuMMC\n");
|
||||
ctxt->emummc_forced = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_atmosphere(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
@@ -196,7 +205,7 @@ static int _config_dis_exo_user_exceptions(launch_ctxt_t *ctxt, const char *valu
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Disabled exosphere user exception handlers\n");
|
||||
ctxt->exo_no_user_exceptions = true;
|
||||
ctxt->exo_cfg.no_user_exceptions = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -206,11 +215,38 @@ static int _config_exo_user_pmu_access(launch_ctxt_t *ctxt, const char *value)
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled user access to PMU\n");
|
||||
ctxt->exo_user_pmu = true;
|
||||
ctxt->exo_cfg.user_pmu = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
ctxt->exo_cfg.cal0_blank = calloc(1, 1);
|
||||
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled prodinfo blanking\n");
|
||||
*ctxt->exo_cfg.cal0_blank = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
// Override key found.
|
||||
ctxt->exo_cfg.cal0_allow_writes_sys = calloc(1, 1);
|
||||
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled prodinfo writes\n");
|
||||
*ctxt->exo_cfg.cal0_allow_writes_sys = true;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_fss(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
||||
@@ -241,9 +277,12 @@ static const cfg_handler_t _config_handlers[] = {
|
||||
{ "debugmode", _config_debugmode },
|
||||
{ "stock", _config_stock },
|
||||
{ "atmosphere", _config_atmosphere },
|
||||
{ "fss0", _config_fss },
|
||||
{ "emummcforce", _config_emummc_forced },
|
||||
{ "nouserexceptions", _config_dis_exo_user_exceptions },
|
||||
{ "userpmu", _config_exo_user_pmu_access },
|
||||
{ "fss0", _config_fss },
|
||||
{ "cal0blank", _config_exo_cal0_blanking },
|
||||
{ "cal0writesys", _config_exo_cal0_writes_enable },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
@@ -254,11 +293,15 @@ int parse_boot_config(launch_ctxt_t *ctxt)
|
||||
for(u32 i = 0; _config_handlers[i].key; i++)
|
||||
{
|
||||
if (!strcmp(_config_handlers[i].key, kv->key))
|
||||
{
|
||||
if (!_config_handlers[i].handler(ctxt, kv->val))
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
EPRINTFARGS("Error while loading %s:\n%s", kv->key, kv->val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "../mem/heap.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../utils/aarch64_util.h"
|
||||
|
||||
#include "../gfx/gfx.h"
|
||||
@@ -35,8 +36,6 @@
|
||||
extern hekate_config h_cfg;
|
||||
extern const u8 package2_keyseed[];
|
||||
|
||||
extern void *sd_file_read(const char *path, u32 *fsize);
|
||||
|
||||
#ifdef KIP1_PATCH_DEBUG
|
||||
#include "../utils/util.h"
|
||||
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
@@ -640,8 +639,22 @@ static kip1_id_t _kip_ids[] =
|
||||
{ "FS", "\x81\x7E\xA2\xB0\xB7\x02\xC1\xF3", _fs_patches_1000 }, // FS 10.0.0 exfat
|
||||
};
|
||||
|
||||
static kip1_id_t *_kip_id_sets = _kip_ids;
|
||||
static u32 _kip_id_sets_cnt = sizeof(_kip_ids) / sizeof(_kip_ids[0]);
|
||||
|
||||
void pkg2_get_ids(kip1_id_t **ids, u32 *entries)
|
||||
{
|
||||
*ids = _kip_id_sets;
|
||||
*entries = _kip_id_sets_cnt;
|
||||
}
|
||||
|
||||
static void parse_external_kip_patches()
|
||||
{
|
||||
static bool ext_patches_done = false;
|
||||
|
||||
if (ext_patches_done)
|
||||
return;
|
||||
|
||||
u32 curr_kip_idx = 0;
|
||||
char path[64];
|
||||
strcpy(path, "bootloader/patches.ini");
|
||||
@@ -649,77 +662,103 @@ static void parse_external_kip_patches()
|
||||
LIST_INIT(ini_kip_sections);
|
||||
if (ini_patch_parse(&ini_kip_sections, path))
|
||||
{
|
||||
// Copy ids into a new patchset.
|
||||
_kip_id_sets = calloc(sizeof(kip1_id_t), 256); // Max 256 kip ids.
|
||||
memcpy(_kip_id_sets, _kip_ids, sizeof(_kip_ids));
|
||||
|
||||
// Parse patchsets and glue them together.
|
||||
LIST_FOREACH_ENTRY(ini_kip_sec_t, ini_psec, &ini_kip_sections, link)
|
||||
{
|
||||
kip1_id_t* curr_kip = &_kip_ids[curr_kip_idx];
|
||||
|
||||
if (!strcmp(curr_kip->name, ini_psec->name) && !memcmp(curr_kip->hash, ini_psec->hash, 8))
|
||||
kip1_id_t* curr_kip = NULL;
|
||||
bool found = false;
|
||||
for (curr_kip_idx = 0; curr_kip_idx < _kip_id_sets_cnt + 1; curr_kip_idx++)
|
||||
{
|
||||
kip1_patchset_t *patchsets = (kip1_patchset_t *)calloc(sizeof(kip1_patchset_t), 8); // Max 8 patchsets per kip.
|
||||
curr_kip = &_kip_id_sets[curr_kip_idx];
|
||||
|
||||
u32 curr_patchset_idx;
|
||||
for(curr_patchset_idx = 0; curr_kip->patchset[curr_patchset_idx].name != NULL; curr_patchset_idx++)
|
||||
if (!curr_kip->name)
|
||||
break;
|
||||
|
||||
if (!strcmp(curr_kip->name, ini_psec->name) && !memcmp(curr_kip->hash, ini_psec->hash, 8))
|
||||
{
|
||||
patchsets[curr_patchset_idx].name = curr_kip->patchset[curr_patchset_idx].name;
|
||||
patchsets[curr_patchset_idx].patches = curr_kip->patchset[curr_patchset_idx].patches;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
curr_kip->patchset = patchsets;
|
||||
bool first_ext_patch = true;
|
||||
u32 curr_patch_idx = 0;
|
||||
if (!curr_kip)
|
||||
continue;
|
||||
|
||||
// Parse patches and glue them together to a patchset.
|
||||
kip1_patch_t *patches = calloc(sizeof(kip1_patch_t), 16); // Max 16 patches per set.
|
||||
LIST_FOREACH_ENTRY(ini_patchset_t, pt, &ini_psec->pts, link)
|
||||
// If not found, create a new empty entry.
|
||||
if (!found)
|
||||
{
|
||||
curr_kip->name = ini_psec->name;
|
||||
memcpy(curr_kip->hash, ini_psec->hash, 8);
|
||||
curr_kip->patchset = calloc(sizeof(kip1_patchset_t), 1);
|
||||
|
||||
_kip_id_sets_cnt++;
|
||||
}
|
||||
|
||||
kip1_patchset_t *patchsets = (kip1_patchset_t *)calloc(sizeof(kip1_patchset_t), 16); // Max 16 patchsets per kip.
|
||||
|
||||
u32 curr_patchset_idx;
|
||||
for(curr_patchset_idx = 0; curr_kip->patchset[curr_patchset_idx].name != NULL; curr_patchset_idx++)
|
||||
{
|
||||
patchsets[curr_patchset_idx].name = curr_kip->patchset[curr_patchset_idx].name;
|
||||
patchsets[curr_patchset_idx].patches = curr_kip->patchset[curr_patchset_idx].patches;
|
||||
}
|
||||
|
||||
curr_kip->patchset = patchsets;
|
||||
bool first_ext_patch = true;
|
||||
u32 curr_patch_idx = 0;
|
||||
|
||||
// Parse patches and glue them together to a patchset.
|
||||
kip1_patch_t *patches = calloc(sizeof(kip1_patch_t), 32); // Max 32 patches per set.
|
||||
LIST_FOREACH_ENTRY(ini_patchset_t, pt, &ini_psec->pts, link)
|
||||
{
|
||||
if (first_ext_patch)
|
||||
{
|
||||
if (first_ext_patch)
|
||||
first_ext_patch = false;
|
||||
patchsets[curr_patchset_idx].name = malloc(strlen(pt->name) + 1);
|
||||
strcpy(patchsets[curr_patchset_idx].name, pt->name);
|
||||
patchsets[curr_patchset_idx].patches = patches;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if new patchset name is found and create a new set.
|
||||
if (strcmp(pt->name, patchsets[curr_patchset_idx].name))
|
||||
{
|
||||
first_ext_patch = false;
|
||||
curr_patchset_idx++;
|
||||
curr_patch_idx = 0;
|
||||
patches = calloc(sizeof(kip1_patch_t), 16); // Max 16 patches per set.
|
||||
|
||||
patchsets[curr_patchset_idx].name = malloc(strlen(pt->name) + 1);
|
||||
strcpy(patchsets[curr_patchset_idx].name, pt->name);
|
||||
patchsets[curr_patchset_idx].patches = patches;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if new patchset name is found and create a new set.
|
||||
if (strcmp(pt->name, patchsets[curr_patchset_idx].name))
|
||||
{
|
||||
curr_patchset_idx++;
|
||||
curr_patch_idx = 0;
|
||||
patches = calloc(sizeof(kip1_patch_t), 16); // Max 16 patches per set.
|
||||
|
||||
patchsets[curr_patchset_idx].name = malloc(strlen(pt->name) + 1);
|
||||
strcpy(patchsets[curr_patchset_idx].name, pt->name);
|
||||
patchsets[curr_patchset_idx].patches = patches;
|
||||
}
|
||||
}
|
||||
|
||||
if (pt->length)
|
||||
{
|
||||
patches[curr_patch_idx].offset = pt->offset;
|
||||
patches[curr_patch_idx].length = pt->length;
|
||||
|
||||
patches[curr_patch_idx].srcData = malloc(pt->length);
|
||||
patches[curr_patch_idx].dstData = malloc(pt->length);
|
||||
memcpy(patches[curr_patch_idx].srcData, pt->srcData, pt->length);
|
||||
memcpy(patches[curr_patch_idx].dstData, pt->dstData, pt->length);
|
||||
}
|
||||
else
|
||||
patches[curr_patch_idx].srcData = malloc(1); // Empty patches check. Keep everything else as 0.
|
||||
|
||||
curr_patch_idx++;
|
||||
}
|
||||
curr_patchset_idx++;
|
||||
patchsets[curr_patchset_idx].name = NULL;
|
||||
patchsets[curr_patchset_idx].patches = NULL;
|
||||
}
|
||||
|
||||
curr_kip_idx++;
|
||||
if (!(curr_kip_idx < (sizeof(_kip_ids) / sizeof(_kip_ids[0]))))
|
||||
break;
|
||||
if (pt->length)
|
||||
{
|
||||
patches[curr_patch_idx].offset = pt->offset;
|
||||
patches[curr_patch_idx].length = pt->length;
|
||||
|
||||
patches[curr_patch_idx].srcData = malloc(pt->length);
|
||||
patches[curr_patch_idx].dstData = malloc(pt->length);
|
||||
memcpy(patches[curr_patch_idx].srcData, pt->srcData, pt->length);
|
||||
memcpy(patches[curr_patch_idx].dstData, pt->dstData, pt->length);
|
||||
}
|
||||
else
|
||||
patches[curr_patch_idx].srcData = malloc(1); // Empty patches check. Keep everything else as 0.
|
||||
|
||||
curr_patch_idx++;
|
||||
}
|
||||
curr_patchset_idx++;
|
||||
patchsets[curr_patchset_idx].name = NULL;
|
||||
patchsets[curr_patchset_idx].patches = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ext_patches_done = true;
|
||||
}
|
||||
|
||||
const pkg2_kernel_id_t *pkg2_identify(u8 *hash)
|
||||
@@ -1041,13 +1080,13 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
|
||||
{
|
||||
shaBuf[0] = 0; // sha256 for this kip not yet calculated.
|
||||
for (u32 currKipIdx = 0; currKipIdx < (sizeof(_kip_ids) / sizeof(_kip_ids[0])); currKipIdx++)
|
||||
for (u32 currKipIdx = 0; currKipIdx < _kip_id_sets_cnt; currKipIdx++)
|
||||
{
|
||||
if (strncmp((const char*)ki->kip1->name, _kip_ids[currKipIdx].name, sizeof(ki->kip1->name)) != 0)
|
||||
if (strncmp((const char*)ki->kip1->name, _kip_id_sets[currKipIdx].name, sizeof(ki->kip1->name)) != 0)
|
||||
continue;
|
||||
|
||||
u32 bitsAffected = 0;
|
||||
kip1_patchset_t* currPatchset = _kip_ids[currKipIdx].patchset;
|
||||
kip1_patchset_t* currPatchset = _kip_id_sets[currKipIdx].patchset;
|
||||
while (currPatchset != NULL && currPatchset->name != NULL)
|
||||
{
|
||||
for (u32 i = 0; i < numPatches; i++)
|
||||
@@ -1071,12 +1110,12 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
memset(shaBuf, 0, sizeof(shaBuf));
|
||||
}
|
||||
|
||||
if (memcmp(shaBuf, _kip_ids[currKipIdx].hash, sizeof(_kip_ids[0].hash)) != 0)
|
||||
if (memcmp(shaBuf, _kip_id_sets[currKipIdx].hash, sizeof(_kip_id_sets[0].hash)) != 0)
|
||||
continue;
|
||||
|
||||
// Find out which sections are affected by the enabled patches, to know which to decompress.
|
||||
bitsAffected = 0;
|
||||
currPatchset = _kip_ids[currKipIdx].patchset;
|
||||
currPatchset = _kip_id_sets[currKipIdx].patchset;
|
||||
while (currPatchset != NULL && currPatchset->name != NULL)
|
||||
{
|
||||
if (currPatchset->patches != NULL)
|
||||
@@ -1111,7 +1150,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
DPRINTF("%dms %s KIP1 size %d hash %08X\n", (postDecompTime-preDecompTime) / 1000, ki->kip1->name, (int)ki->size, __builtin_bswap32(shaBuf[0]));
|
||||
#endif
|
||||
|
||||
currPatchset = _kip_ids[currKipIdx].patchset;
|
||||
currPatchset = _kip_id_sets[currKipIdx].patchset;
|
||||
bool emummc_patch_selected = false;
|
||||
while (currPatchset != NULL && currPatchset->name != NULL)
|
||||
{
|
||||
@@ -1180,7 +1219,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
}
|
||||
currPatchset++;
|
||||
}
|
||||
if (emummc_patch_selected && !strncmp(_kip_ids[currKipIdx].name, "FS", 2))
|
||||
if (emummc_patch_selected && !strncmp(_kip_id_sets[currKipIdx].name, "FS", 2))
|
||||
{
|
||||
emummc_patch_selected = false;
|
||||
emu_cfg.fs_ver = currKipIdx;
|
||||
@@ -1215,7 +1254,6 @@ static const u8 mkey_keyseed_8xx[][0x10] =
|
||||
|
||||
static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed)
|
||||
{
|
||||
|
||||
// Decrypt older encrypted mkey.
|
||||
se_aes_crypt_ecb(src_slot, 0, mkey, 0x10, key_seed, 0x10);
|
||||
// Set and unwrap pkg2 key.
|
||||
@@ -1276,7 +1314,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
|
||||
mkey_seeds_idx--;
|
||||
se_aes_key_clear(9);
|
||||
se_aes_key_set(9, tmp_mkey, 0x10);
|
||||
|
||||
|
||||
decr_slot = 9; // Temp key.
|
||||
|
||||
// Check if we tried last key for that pkg2 version.
|
||||
|
||||
@@ -149,6 +149,7 @@ int pkg2_has_kip(link_t *info, u64 tid);
|
||||
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
|
||||
void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1);
|
||||
void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1);
|
||||
void pkg2_get_ids(kip1_id_t **ids, u32 *entries);
|
||||
const char* pkg2_patch_kips(link_t *info, char* patchNames);
|
||||
|
||||
const pkg2_kernel_id_t *pkg2_identify(u8 *hash);
|
||||
|
||||
@@ -72,12 +72,9 @@ static u32 _find_patch_section_name(char *lbuf, u32 lblen, char schar)
|
||||
static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec, char *name)
|
||||
{
|
||||
if (ksec)
|
||||
{
|
||||
list_append(dst, &ksec->link);
|
||||
ksec = NULL;
|
||||
}
|
||||
|
||||
ksec = (ini_kip_sec_t *)malloc(sizeof(ini_kip_sec_t));
|
||||
ksec = (ini_kip_sec_t *)calloc(sizeof(ini_kip_sec_t), 1);
|
||||
u32 i = _find_patch_section_name(name, strlen(name), ':') + 1;
|
||||
ksec->name = _strdup(name);
|
||||
|
||||
@@ -105,8 +102,8 @@ int ini_patch_parse(link_t *dst, char *ini_path)
|
||||
f_gets(lbuf, 512, &fp);
|
||||
lblen = strlen(lbuf);
|
||||
|
||||
// Remove trailing newline.
|
||||
if (lbuf[lblen - 1] == '\n' || lbuf[lblen - 1] == '\r')
|
||||
// Remove trailing newline. Depends on 'FF_USE_STRFUNC 2' that removes \r.
|
||||
if (lblen && lbuf[lblen - 1] == '\n')
|
||||
lbuf[lblen - 1] = 0;
|
||||
|
||||
if (lblen > 2 && lbuf[0] == '[') // Create new section.
|
||||
@@ -121,7 +118,7 @@ int ini_patch_parse(link_t *dst, char *ini_path)
|
||||
u32 tmp = 0;
|
||||
u32 i = _find_patch_section_name(lbuf, lblen, '=');
|
||||
|
||||
ini_patchset_t *pt = (ini_patchset_t *)malloc(sizeof(ini_patchset_t));
|
||||
ini_patchset_t *pt = (ini_patchset_t *)calloc(sizeof(ini_patchset_t), 1);
|
||||
|
||||
pt->name = _strdup(&lbuf[1]);
|
||||
|
||||
@@ -145,13 +142,7 @@ int ini_patch_parse(link_t *dst, char *ini_path)
|
||||
i += tmp + 1;
|
||||
pt->dstData = _htoa(NULL, &lbuf[i], pt->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
pt->offset = 0;
|
||||
pt->length = 0;
|
||||
pt->srcData = NULL;
|
||||
pt->dstData = NULL;
|
||||
}
|
||||
|
||||
list_append(&ksec->pts, &pt->link);
|
||||
}
|
||||
} while (!f_eof(&fp));
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "../mem/heap.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/util.h"
|
||||
@@ -33,9 +34,6 @@
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
|
||||
enum emuMMC_Type
|
||||
{
|
||||
emuMMC_None = 0,
|
||||
@@ -132,17 +130,22 @@ typedef struct _atm_fatal_error_ctx
|
||||
|
||||
// Exosphère mailbox defines.
|
||||
#define EXO_CFG_ADDR 0x8000F000
|
||||
#define EXO_MAGIC_VAL 0x304F5845
|
||||
#define EXO_FLAG_DBG_PRIV (1 << 1)
|
||||
#define EXO_FLAG_DBG_USER (1 << 2)
|
||||
#define EXO_FLAG_NO_USER_EXC (1 << 3)
|
||||
#define EXO_FLAG_USER_PMU (1 << 4)
|
||||
#define EXO_MAGIC_VAL 0x304F5845
|
||||
#define EXO_FLAG_DBG_PRIV (1 << 1)
|
||||
#define EXO_FLAG_DBG_USER (1 << 2)
|
||||
#define EXO_FLAG_NO_USER_EXC (1 << 3)
|
||||
#define EXO_FLAG_USER_PMU (1 << 4)
|
||||
#define EXO_FLAG_CAL0_BLANKING (1 << 5)
|
||||
#define EXO_FLAG_CAL0_WRITES_SYS (1 << 6)
|
||||
|
||||
void config_exosphere(launch_ctxt_t *ctxt)
|
||||
{
|
||||
u32 exoFwNo = 0;
|
||||
u32 exoFlags = 0;
|
||||
u32 kb = ctxt->pkg1_id->kb;
|
||||
bool user_debug = false;
|
||||
bool cal0_blanking = false;
|
||||
bool cal0_allow_writes_sys = false;
|
||||
|
||||
memset((exo_cfg_t *)EXO_CFG_ADDR, 0, sizeof(exo_cfg_t));
|
||||
|
||||
@@ -168,23 +171,69 @@ void config_exosphere(launch_ctxt_t *ctxt)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ctxt->stock)
|
||||
{
|
||||
// Parse exosphere.ini.
|
||||
LIST_INIT(ini_sections);
|
||||
if (ini_parse(&ini_sections, "exosphere.ini", false))
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
// Only parse exosphere section.
|
||||
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "exosphere"))
|
||||
continue;
|
||||
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||
{
|
||||
if (!strcmp("debugmode_user", kv->key))
|
||||
user_debug = atoi(kv->val);
|
||||
else if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
|
||||
{
|
||||
if (!strcmp("blank_prodinfo_emummc", kv->key))
|
||||
cal0_blanking = atoi(kv->val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcmp("blank_prodinfo_sysmmc", kv->key))
|
||||
cal0_blanking = atoi(kv->val);
|
||||
else if (!strcmp("allow_writing_to_cal_sysmmc", kv->key))
|
||||
cal0_allow_writes_sys = atoi(kv->val);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To avoid problems, make private debug mode always on if not semi-stock.
|
||||
if (!ctxt->stock || (emu_cfg.enabled && !h_cfg.emummc_force_disable))
|
||||
exoFlags |= EXO_FLAG_DBG_PRIV;
|
||||
|
||||
// Enable user debug.
|
||||
if (user_debug)
|
||||
exoFlags |= EXO_FLAG_DBG_USER;
|
||||
|
||||
// Disable proper failure handling.
|
||||
if (ctxt->exo_no_user_exceptions)
|
||||
if (ctxt->exo_cfg.no_user_exceptions)
|
||||
exoFlags |= EXO_FLAG_NO_USER_EXC;
|
||||
|
||||
// Enable user access to PMU.
|
||||
if (ctxt->exo_user_pmu)
|
||||
if (ctxt->exo_cfg.user_pmu)
|
||||
exoFlags |= EXO_FLAG_USER_PMU;
|
||||
|
||||
// Check if exo ini value is overridden and enable prodinfo blanking.
|
||||
if ((ctxt->exo_cfg.cal0_blank && *ctxt->exo_cfg.cal0_blank)
|
||||
|| (!ctxt->exo_cfg.cal0_blank && cal0_blanking))
|
||||
exoFlags |= EXO_FLAG_CAL0_BLANKING;
|
||||
|
||||
// Check if exo ini value is overridden and allow prodinfo writes.
|
||||
if ((ctxt->exo_cfg.cal0_allow_writes_sys && *ctxt->exo_cfg.cal0_allow_writes_sys)
|
||||
|| (!ctxt->exo_cfg.cal0_allow_writes_sys && cal0_allow_writes_sys))
|
||||
exoFlags |= EXO_FLAG_CAL0_WRITES_SYS;
|
||||
|
||||
// Set mailbox values.
|
||||
exo_cfg->magic = EXO_MAGIC_VAL;
|
||||
|
||||
exo_cfg->fwno = exoFwNo;
|
||||
|
||||
exo_cfg->flags = exoFlags;
|
||||
|
||||
// If warmboot is lp0fw, add in RSA modulus.
|
||||
@@ -200,8 +249,8 @@ void config_exosphere(launch_ctxt_t *ctxt)
|
||||
// Set warmboot binary rsa modulus.
|
||||
u8 *rsa_mod = (u8 *)malloc(512);
|
||||
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 1, 1, rsa_mod);
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/types.h"
|
||||
@@ -65,17 +66,13 @@ extern boot_cfg_t b_cfg;
|
||||
extern hekate_config h_cfg;
|
||||
extern const volatile ipl_ver_meta_t ipl_ver;
|
||||
|
||||
extern void *sd_file_read(char *path);
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount();
|
||||
extern bool is_ipl_updated(void *buf);
|
||||
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
|
||||
|
||||
extern sdmmc_t sd_sdmmc;
|
||||
extern sdmmc_storage_t sd_storage;
|
||||
|
||||
void check_sept(ini_sec_t *cfg_sec)
|
||||
{
|
||||
hos_eks_get();
|
||||
|
||||
// Check if non-hekate payload is used for sept and restore it.
|
||||
if (h_cfg.sept_run)
|
||||
{
|
||||
@@ -103,7 +100,7 @@ void check_sept(ini_sec_t *cfg_sec)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
emummc_storage_set_mmc_partition(&storage, 1);
|
||||
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
// Read package1.
|
||||
emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
@@ -117,6 +114,14 @@ void check_sept(ini_sec_t *cfg_sec)
|
||||
|
||||
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
|
||||
{
|
||||
u8 key_idx = pkg1_id->kb - KB_FIRMWARE_VERSION_700;
|
||||
if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx)))
|
||||
{
|
||||
h_cfg.sept_run = true;
|
||||
EMC(EMC_SCRATCH0) |= EMC_SEPT_RUN;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off, pkg1_id->kb, cfg_sec);
|
||||
}
|
||||
|
||||
@@ -18,21 +18,18 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "ianos.h"
|
||||
#include "../utils/types.h"
|
||||
#include "../libs/elfload/elfload.h"
|
||||
#include "../../common/common_module.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../libs/elfload/elfload.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
#define IRAM_LIB_ADDR 0x4002B000
|
||||
#define DRAM_LIB_ADDR 0xE0000000
|
||||
|
||||
extern heap_t _heap;
|
||||
|
||||
extern void *sd_file_read(const char *path, u32 *fsize);
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount();
|
||||
|
||||
void *elfBuf = NULL;
|
||||
void *fileBuf = NULL;
|
||||
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
#include "../../../common/memory_map.h"
|
||||
|
||||
#include "diskio.h" /* FatFs lower layer API */
|
||||
#include "../../storage/nx_sd.h"
|
||||
#include "../../storage/sdmmc.h"
|
||||
|
||||
extern sdmmc_storage_t sd_storage;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Get Drive Status */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@@ -46,16 +45,7 @@ DRESULT disk_read (
|
||||
UINT count /* Number of sectors to read */
|
||||
)
|
||||
{
|
||||
// Ensure that buffer resides in DRAM and it's DMA aligned.
|
||||
if (((u32)buff >= DRAM_START) && !((u32)buff % 8))
|
||||
return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR;
|
||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
if (sdmmc_storage_read(&sd_storage, sector, count, buf))
|
||||
{
|
||||
memcpy(buff, buf, 512 * count);
|
||||
return RES_OK;
|
||||
}
|
||||
return RES_ERROR;
|
||||
return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@@ -68,14 +58,7 @@ DRESULT disk_write (
|
||||
UINT count /* Number of sectors to write */
|
||||
)
|
||||
{
|
||||
// Ensure that buffer resides in DRAM and it's DMA aligned.
|
||||
if (((u32)buff >= DRAM_START) && !((u32)buff % 8))
|
||||
return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
|
||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
memcpy(buf, buff, 512 * count);
|
||||
if (sdmmc_storage_write(&sd_storage, sector, count, buf))
|
||||
return RES_OK;
|
||||
return RES_ERROR;
|
||||
return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
@@ -47,6 +47,7 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||
/* Generic command (Used by FatFs) */
|
||||
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
|
||||
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
|
||||
#define SET_SECTOR_COUNT 1 /* Set media size (needed at FF_USE_MKFS == 1) */
|
||||
#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 CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
|
||||
|
||||
@@ -5694,7 +5694,7 @@ FRESULT f_mkfs (
|
||||
} else {
|
||||
/* Create a single-partition in this function */
|
||||
if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
|
||||
b_vol = (opt & FM_SFD) ? 0 : 63; /* Volume start sector */
|
||||
b_vol = (opt & FM_SFD) ? 0 : 32768; /* Volume start sector. Align to 16MB */
|
||||
if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);
|
||||
sz_vol -= b_vol; /* Volume size */
|
||||
}
|
||||
@@ -5981,13 +5981,13 @@ FRESULT f_mkfs (
|
||||
st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */
|
||||
buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */
|
||||
buf[BS_BootSig32] = 0x29; /* Extended boot signature */
|
||||
mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */
|
||||
mem_cpy(buf + BS_VolLab32, "SWITCH SD " "FAT32 ", 19); /* Volume label, FAT signature */
|
||||
} else {
|
||||
st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */
|
||||
st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
|
||||
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
|
||||
buf[BS_BootSig] = 0x29; /* Extended boot signature */
|
||||
mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
|
||||
mem_cpy(buf + BS_VolLab, "SWITCH SD " "FAT ", 19); /* Volume label, FAT signature */
|
||||
}
|
||||
st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */
|
||||
if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */
|
||||
|
||||
@@ -368,8 +368,11 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
|
||||
#define AM_RDO 0x01 /* Read only */
|
||||
#define AM_HID 0x02 /* Hidden */
|
||||
#define AM_SYS 0x04 /* System */
|
||||
#define AM_VOL 0x08 /* Volume */
|
||||
#define AM_DIR 0x10 /* Directory */
|
||||
#define AM_ARC 0x20 /* Archive */
|
||||
#define AM_DEV 0x40 /* Device */
|
||||
#define AM_RVD 0x80 /* Reserved */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -7,6 +7,7 @@ SECTIONS {
|
||||
*(.text._start);
|
||||
*(._boot_cfg);
|
||||
*(._ipl_version);
|
||||
*(.text._irq_setup);
|
||||
*(.text*);
|
||||
}
|
||||
.data : {
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "soc/uart.h"
|
||||
#include "storage/emummc.h"
|
||||
#include "storage/nx_emmc.h"
|
||||
#include "storage/nx_sd.h"
|
||||
#include "storage/sdmmc.h"
|
||||
#include "utils/btn.h"
|
||||
#include "utils/dirlist.h"
|
||||
@@ -58,12 +59,6 @@
|
||||
#include "frontend/fe_tools.h"
|
||||
#include "frontend/fe_info.h"
|
||||
|
||||
//TODO: ugly.
|
||||
sdmmc_t sd_sdmmc;
|
||||
sdmmc_storage_t sd_storage;
|
||||
FATFS sd_fs;
|
||||
static bool sd_mounted;
|
||||
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
u8 *Kc_MENU_LOGO;
|
||||
#endif //MENU_LOGO_ENABLE
|
||||
@@ -79,87 +74,6 @@ const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver
|
||||
|
||||
volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR;
|
||||
|
||||
bool sd_mount()
|
||||
{
|
||||
if (sd_mounted)
|
||||
return true;
|
||||
|
||||
if (!sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_1, SDMMC_BUS_WIDTH_4, 11))
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
EPRINTF("Failed to init SD card.\nMake sure that it is inserted.\nOr that SD reader is properly seated!");
|
||||
}
|
||||
else
|
||||
{
|
||||
int res = 0;
|
||||
res = f_mount(&sd_fs, "", 1);
|
||||
if (res == FR_OK)
|
||||
{
|
||||
sd_mounted = 1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
EPRINTFARGS("Failed to mount SD card (FatFS Error %d).\nMake sure that a FAT partition exists..", res);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void sd_unmount()
|
||||
{
|
||||
if (sd_mounted)
|
||||
{
|
||||
f_mount(NULL, "", 1);
|
||||
sdmmc_storage_end(&sd_storage);
|
||||
sd_mounted = false;
|
||||
}
|
||||
}
|
||||
|
||||
void *sd_file_read(const char *path, u32 *fsize)
|
||||
{
|
||||
FIL fp;
|
||||
if (f_open(&fp, path, FA_READ) != FR_OK)
|
||||
return NULL;
|
||||
|
||||
u32 size = f_size(&fp);
|
||||
if (fsize)
|
||||
*fsize = size;
|
||||
|
||||
void *buf = malloc(size);
|
||||
|
||||
if (f_read(&fp, buf, size, NULL) != FR_OK)
|
||||
{
|
||||
free(buf);
|
||||
f_close(&fp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f_close(&fp);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int sd_save_to_file(void *buf, u32 size, const char *filename)
|
||||
{
|
||||
FIL fp;
|
||||
u32 res = 0;
|
||||
res = f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (res)
|
||||
{
|
||||
EPRINTFARGS("Error (%d) creating file\n%s.\n", res, filename);
|
||||
return res;
|
||||
}
|
||||
|
||||
f_write(&fp, buf, size, NULL);
|
||||
f_close(&fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_storage_t storage2;
|
||||
@@ -172,7 +86,7 @@ void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t
|
||||
|
||||
if (!storage)
|
||||
{
|
||||
if (!sdmmc_storage_init_mmc(&storage2, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage2, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
memcpy(emmcSN, "00000000", 9);
|
||||
else
|
||||
{
|
||||
@@ -280,7 +194,7 @@ bool is_ipl_updated(void *buf, char *path, bool force)
|
||||
|
||||
f_open(&fp, path, FA_WRITE | FA_CREATE_ALWAYS);
|
||||
f_write(&fp, (u8 *)reloc->start, reloc->end - reloc->start, NULL);
|
||||
|
||||
|
||||
// Write needed tag in case injected ipl uses old versioning.
|
||||
f_write(&fp, "ICTC49", 6, NULL);
|
||||
|
||||
@@ -326,7 +240,7 @@ int launch_payload(char *path, bool update)
|
||||
if (f_read(&fp, buf, size, NULL))
|
||||
{
|
||||
f_close(&fp);
|
||||
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -476,6 +390,7 @@ void ini_list_launcher()
|
||||
{
|
||||
u8 max_entries = 61;
|
||||
char *payload_path = NULL;
|
||||
char *emummc_path = NULL;
|
||||
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
LIST_INIT(ini_list_sections);
|
||||
@@ -539,6 +454,20 @@ void ini_list_launcher()
|
||||
|
||||
payload_path = ini_check_payload_section(cfg_sec);
|
||||
|
||||
if (cfg_sec)
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg_sec->kvs, link)
|
||||
{
|
||||
if (!strcmp("emummc_force_disable", kv->key))
|
||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||
else if (!strcmp("emupath", kv->key))
|
||||
emummc_path = kv->val;
|
||||
}
|
||||
}
|
||||
|
||||
if (emummc_path)
|
||||
emummc_set_path(emummc_path);
|
||||
|
||||
if (cfg_sec && !payload_path)
|
||||
check_sept(cfg_sec);
|
||||
|
||||
@@ -569,6 +498,13 @@ void ini_list_launcher()
|
||||
else if (!hos_launch(cfg_sec))
|
||||
{
|
||||
EPRINTF("Failed to launch firmware.");
|
||||
|
||||
if (emummc_path)
|
||||
{
|
||||
sd_mount();
|
||||
emummc_load_cfg();
|
||||
}
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
@@ -581,6 +517,7 @@ void launch_firmware()
|
||||
{
|
||||
u8 max_entries = 61;
|
||||
char *payload_path = NULL;
|
||||
char *emummc_path = NULL;
|
||||
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
LIST_INIT(ini_sections);
|
||||
@@ -663,9 +600,14 @@ void launch_firmware()
|
||||
{
|
||||
if (!strcmp("emummc_force_disable", kv->key))
|
||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||
if (!strcmp("emupath", kv->key))
|
||||
emummc_path = kv->val;
|
||||
}
|
||||
}
|
||||
|
||||
if (emummc_path)
|
||||
emummc_set_path(emummc_path);
|
||||
|
||||
if (cfg_sec && !payload_path)
|
||||
check_sept(cfg_sec);
|
||||
|
||||
@@ -699,7 +641,14 @@ void launch_firmware()
|
||||
free(payload_path);
|
||||
}
|
||||
else if (!hos_launch(cfg_sec))
|
||||
{
|
||||
EPRINTF("Failed to launch firmware.");
|
||||
if (emummc_path)
|
||||
{
|
||||
sd_mount();
|
||||
emummc_load_cfg();
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
sd_unmount();
|
||||
@@ -747,10 +696,19 @@ void nyx_load_run()
|
||||
|
||||
nyx_str->info.errors = h_cfg.errors;
|
||||
nyx_str->cfg = 0;
|
||||
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_DUMP)
|
||||
if (b_cfg.extra_cfg)
|
||||
{
|
||||
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_DUMP);
|
||||
nyx_str->cfg |= NYX_CFG_DUMP;
|
||||
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_DUMP)
|
||||
{
|
||||
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_DUMP);
|
||||
nyx_str->cfg |= NYX_CFG_DUMP;
|
||||
}
|
||||
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_UMS)
|
||||
{
|
||||
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_UMS);
|
||||
nyx_str->cfg |= NYX_CFG_UMS;
|
||||
nyx_str->cfg |= b_cfg.ums << 24;
|
||||
}
|
||||
}
|
||||
|
||||
nyx_str->version = ipl_ver.version - 0x303030; // Convert ASCII to numbers.
|
||||
@@ -771,7 +729,7 @@ void nyx_load_run()
|
||||
(*nyx_ptr)();
|
||||
}
|
||||
|
||||
static ini_sec_t *get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomEntry)
|
||||
static ini_sec_t *get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomEntry, char **emummc_path)
|
||||
{
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
|
||||
@@ -788,10 +746,13 @@ static ini_sec_t *get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomE
|
||||
*bootlogoCustomEntry = kv->val;
|
||||
if (!strcmp("emummc_force_disable", kv->key))
|
||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||
if (!strcmp("emupath", kv->key))
|
||||
*emummc_path = kv->val;
|
||||
}
|
||||
if (!cfg_sec)
|
||||
{
|
||||
*bootlogoCustomEntry = NULL;
|
||||
*emummc_path = NULL;
|
||||
h_cfg.emummc_force_disable = false;
|
||||
}
|
||||
|
||||
@@ -806,12 +767,15 @@ static void _auto_launch_firmware()
|
||||
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
|
||||
check_sept(NULL);
|
||||
}
|
||||
else if (b_cfg.extra_cfg & EXTRA_CFG_NYX_UMS)
|
||||
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
|
||||
|
||||
if (!h_cfg.sept_run)
|
||||
auto_launch_update();
|
||||
|
||||
u8 *BOOTLOGO = NULL;
|
||||
char *payload_path = NULL;
|
||||
char *emummc_path = NULL;
|
||||
u32 btn = 0;
|
||||
bool boot_from_id = (b_cfg.boot_cfg & BOOT_CFG_FROM_ID) && (b_cfg.boot_cfg & BOOT_CFG_AUTOBOOT_EN);
|
||||
if (boot_from_id)
|
||||
@@ -902,7 +866,7 @@ static void _auto_launch_firmware()
|
||||
}
|
||||
|
||||
if (boot_from_id)
|
||||
cfg_sec = get_ini_sec_from_id(ini_sec, &bootlogoCustomEntry);
|
||||
cfg_sec = get_ini_sec_from_id(ini_sec, &bootlogoCustomEntry, &emummc_path);
|
||||
else if (h_cfg.autoboot == boot_entry_id && configEntry)
|
||||
{
|
||||
cfg_sec = ini_sec;
|
||||
@@ -910,8 +874,10 @@ static void _auto_launch_firmware()
|
||||
{
|
||||
if (!strcmp("logopath", kv->key))
|
||||
bootlogoCustomEntry = kv->val;
|
||||
if (!strcmp("emummc_force_disable", kv->key))
|
||||
else if (!strcmp("emummc_force_disable", kv->key))
|
||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||
else if (!strcmp("emupath", kv->key))
|
||||
emummc_path = kv->val;
|
||||
}
|
||||
}
|
||||
if (cfg_sec)
|
||||
@@ -942,7 +908,7 @@ static void _auto_launch_firmware()
|
||||
continue;
|
||||
|
||||
if (boot_from_id)
|
||||
cfg_sec = get_ini_sec_from_id(ini_sec_list, &bootlogoCustomEntry);
|
||||
cfg_sec = get_ini_sec_from_id(ini_sec_list, &bootlogoCustomEntry, &emummc_path);
|
||||
else if (h_cfg.autoboot == boot_entry_id)
|
||||
{
|
||||
h_cfg.emummc_force_disable = false;
|
||||
@@ -951,8 +917,10 @@ static void _auto_launch_firmware()
|
||||
{
|
||||
if (!strcmp("logopath", kv->key))
|
||||
bootlogoCustomEntry = kv->val;
|
||||
if (!strcmp("emummc_force_disable", kv->key))
|
||||
else if (!strcmp("emummc_force_disable", kv->key))
|
||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||
else if (!strcmp("emupath", kv->key))
|
||||
emummc_path = kv->val;
|
||||
}
|
||||
}
|
||||
if (cfg_sec)
|
||||
@@ -1064,9 +1032,19 @@ skip_list:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC)
|
||||
emummc_set_path(b_cfg.emummc_path);
|
||||
else if (emummc_path)
|
||||
emummc_set_path(emummc_path);
|
||||
check_sept(cfg_sec);
|
||||
hos_launch(cfg_sec);
|
||||
|
||||
if (emummc_path || b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC)
|
||||
{
|
||||
sd_mount();
|
||||
emummc_load_cfg();
|
||||
}
|
||||
|
||||
EPRINTF("\nFailed to launch HOS!");
|
||||
gfx_printf("\nPress any key...\n");
|
||||
msleep(500);
|
||||
@@ -1077,9 +1055,9 @@ out:
|
||||
gfx_con.mute = false;
|
||||
|
||||
// Clear boot reasons from binary.
|
||||
if (b_cfg.boot_cfg & BOOT_CFG_FROM_ID)
|
||||
if (b_cfg.boot_cfg & (BOOT_CFG_FROM_ID | BOOT_CFG_TO_EMUMMC))
|
||||
memset(b_cfg.xt_str, 0, sizeof(b_cfg.xt_str));
|
||||
b_cfg.boot_cfg &= ~(BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_FROM_LAUNCH | BOOT_CFG_FROM_ID);
|
||||
b_cfg.boot_cfg &= ~(BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_FROM_LAUNCH | BOOT_CFG_FROM_ID | BOOT_CFG_TO_EMUMMC);
|
||||
h_cfg.emummc_force_disable = false;
|
||||
|
||||
nyx_load_run();
|
||||
@@ -1098,11 +1076,11 @@ static void _patched_rcm_protection()
|
||||
return;
|
||||
|
||||
// Check if AutoRCM is enabled and protect from a permanent brick.
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
return;
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
u8 corr_mod_byte0;
|
||||
int i, sect = 0;
|
||||
@@ -1129,8 +1107,24 @@ static void _patched_rcm_protection()
|
||||
sdmmc_storage_end(&storage);
|
||||
}
|
||||
|
||||
#define EXCP_EN_ADDR 0x4003FFFC
|
||||
#define EXCP_MAGIC 0x30505645 // EVP0
|
||||
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||||
#define EXCP_TYPE_RESET 0x545352 // RST
|
||||
#define EXCP_TYPE_UNDEF 0x464455 // UDF
|
||||
#define EXCP_TYPE_PABRT 0x54424150 // PABT
|
||||
#define EXCP_TYPE_DABRT 0x54424144 // DABT
|
||||
#define EXCP_LR_ADDR 0x4003FFF4
|
||||
|
||||
static void _show_errors()
|
||||
{
|
||||
u32 *excp_enabled = (u32 *)EXCP_EN_ADDR;
|
||||
u32 *excp_type = (u32 *)EXCP_TYPE_ADDR;
|
||||
u32 *excp_lr = (u32 *)EXCP_LR_ADDR;
|
||||
|
||||
if (*excp_enabled == EXCP_MAGIC)
|
||||
h_cfg.errors |= ERR_EXCEPT_ENB;
|
||||
|
||||
if (h_cfg.errors)
|
||||
{
|
||||
gfx_clear_grey(0x1B);
|
||||
@@ -1138,11 +1132,39 @@ static void _show_errors()
|
||||
display_backlight_brightness(150, 1000);
|
||||
|
||||
if (h_cfg.errors & ERR_LIBSYS_LP0)
|
||||
WPRINTF("Missing LP0 (sleep mode) library!\n");
|
||||
WPRINTF("Missing LP0 (sleep mode) lib!\n");
|
||||
if (h_cfg.errors & ERR_SYSOLD_MTC)
|
||||
WPRINTF("Missing or old Minerva library!\n");
|
||||
WPRINTF("Missing or old Minerva lib!\n");
|
||||
|
||||
if (h_cfg.errors & ~ERR_EXCEPT_ENB)
|
||||
{
|
||||
WPRINTF("\nUpdate bootloader folder!\n\n");
|
||||
}
|
||||
|
||||
if (h_cfg.errors & ERR_EXCEPT_ENB)
|
||||
{
|
||||
WPRINTFARGS("An exception occurred (LR %08X):\n", *excp_lr);
|
||||
switch (*excp_type)
|
||||
{
|
||||
case EXCP_TYPE_RESET:
|
||||
WPRINTF("Reset");
|
||||
break;
|
||||
case EXCP_TYPE_UNDEF:
|
||||
WPRINTF("Undefined instruction");
|
||||
break;
|
||||
case EXCP_TYPE_PABRT:
|
||||
WPRINTF("Prefetch abort");
|
||||
break;
|
||||
case EXCP_TYPE_DABRT:
|
||||
WPRINTF("Data abort");
|
||||
break;
|
||||
}
|
||||
WPRINTF("\n");
|
||||
|
||||
// Clear the exception.
|
||||
*excp_enabled = 0;
|
||||
}
|
||||
|
||||
WPRINTF("\nUpdate your bootloader folder!\n\n");
|
||||
WPRINTF("Press any key...");
|
||||
|
||||
msleep(2000);
|
||||
@@ -1254,7 +1276,7 @@ static void _check_low_battery()
|
||||
free(battery_icon);
|
||||
free(charging_icon);
|
||||
free(no_charging_icon);
|
||||
|
||||
|
||||
// Re enable Low Battery Monitor shutdown.
|
||||
max77620_low_battery_monitor_config(true);
|
||||
}
|
||||
@@ -1316,30 +1338,30 @@ ment_t ment_options[] = {
|
||||
MDEF_BACK(),
|
||||
MDEF_CHGLINE(),
|
||||
MDEF_HANDLER("Auto boot", config_autoboot),
|
||||
MDEF_HANDLER("Boot time delay", config_bootdelay),
|
||||
MDEF_HANDLER("Auto NoGC", config_nogc),
|
||||
//MDEF_HANDLER("Boot delay", config_bootdelay),
|
||||
//MDEF_HANDLER("Auto NoGC", config_nogc),
|
||||
//MDEF_HANDLER("Auto HOS power off", config_auto_hos_poweroff),
|
||||
//MDEF_HANDLER("Backlight", config_backlight),
|
||||
MDEF_HANDLER("Backlight", config_backlight),
|
||||
MDEF_END()
|
||||
};
|
||||
|
||||
menu_t menu_options = { ment_options, "Launch Options", 0, 0 };
|
||||
menu_t menu_options = { ment_options, "Options", 0, 0 };
|
||||
|
||||
ment_t ment_cinfo[] = {
|
||||
MDEF_BACK(),
|
||||
MDEF_CHGLINE(),
|
||||
MDEF_CAPTION("---- SoC Info ----", 0xFF0AB9E6),
|
||||
MDEF_HANDLER("Ipatches & bootrom info", bootrom_ipatches_info),
|
||||
MDEF_HANDLER("Print fuse info", print_fuseinfo),
|
||||
MDEF_HANDLER("Ipatches & bootrom", bootrom_ipatches_info),
|
||||
MDEF_HANDLER("Fuses", print_fuseinfo),
|
||||
//MDEF_HANDLER("Print kfuse info", print_kfuseinfo),
|
||||
MDEF_HANDLER("Print TSEC keys", print_tsec_key),
|
||||
//MDEF_HANDLER("Print TSEC keys", print_tsec_key),
|
||||
MDEF_CHGLINE(),
|
||||
MDEF_CAPTION("-- Storage Info --", 0xFF0AB9E6),
|
||||
MDEF_HANDLER("Print eMMC info", print_mmc_info),
|
||||
MDEF_HANDLER("Print SD Card info", print_sdcard_info),
|
||||
MDEF_HANDLER("eMMC", print_mmc_info),
|
||||
MDEF_HANDLER("SD Card", print_sdcard_info),
|
||||
MDEF_CHGLINE(),
|
||||
MDEF_CAPTION("------ Misc ------", 0xFF0AB9E6),
|
||||
MDEF_HANDLER("Print battery info", print_battery_info),
|
||||
MDEF_HANDLER("Battery", print_battery_info),
|
||||
MDEF_END()
|
||||
};
|
||||
|
||||
@@ -1377,10 +1399,10 @@ menu_t menu_backup = { ment_backup, "Backup Options", 0, 0 };
|
||||
ment_t ment_tools[] = {
|
||||
MDEF_BACK(),
|
||||
MDEF_CHGLINE(),
|
||||
MDEF_CAPTION("-- Backup & Restore --", 0xFF0AB9E6),
|
||||
MDEF_MENU("Backup", &menu_backup),
|
||||
MDEF_MENU("Restore", &menu_restore),
|
||||
MDEF_CHGLINE(),
|
||||
//MDEF_CAPTION("-- Backup & Restore --", 0xFF0AB9E6),
|
||||
//MDEF_MENU("Backup", &menu_backup),
|
||||
//MDEF_MENU("Restore", &menu_restore),
|
||||
//MDEF_CHGLINE(),
|
||||
//MDEF_CAPTION("-------- Misc --------", 0xFF0AB9E6),
|
||||
//MDEF_HANDLER("Dump package1/2", dump_packages12),
|
||||
//MDEF_HANDLER("Fix archive bit (except Nintendo)", fix_sd_all_attr),
|
||||
@@ -1410,7 +1432,7 @@ ment_t ment_top[] = {
|
||||
MDEF_END()
|
||||
};
|
||||
|
||||
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.1.4", 0, 0 };
|
||||
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.2.0", 0, 0 };
|
||||
|
||||
extern void pivot_stack(u32 stack_top);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* arch/arm/mach-tegra/tegra21_emc.h
|
||||
*
|
||||
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2019-2020, CTCaer.
|
||||
*
|
||||
* 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
|
||||
@@ -231,6 +232,7 @@
|
||||
#define EMC_COMP_PAD_SW_CTRL 0x57c
|
||||
#define EMC_REQ_CTRL 0x2b0
|
||||
#define EMC_EMC_STATUS 0x2b4
|
||||
#define EMC_STATUS_MRR_DIVLD (1 << 20)
|
||||
#define EMC_CFG_2 0x2b8
|
||||
#define EMC_CFG_DIG_DLL 0x2bc
|
||||
#define EMC_CFG_DIG_DLL_PERIOD 0x2c0
|
||||
@@ -664,4 +666,28 @@
|
||||
#define EMC_PMC_SCRATCH2 0x444
|
||||
#define EMC_PMC_SCRATCH3 0x448
|
||||
|
||||
#define EMC_STATUS_UPDATE_TIMEOUT 1000
|
||||
|
||||
typedef enum _emc_mr_t
|
||||
{
|
||||
MR5_MAN_ID = 5,
|
||||
MR6_REV_ID1 = 6,
|
||||
MR7_REV_ID2 = 7,
|
||||
MR8_DENSITY = 8,
|
||||
} emc_mr_t;
|
||||
|
||||
enum
|
||||
{
|
||||
EMC_CHAN0 = 0,
|
||||
EMC_CHAN1 = 1
|
||||
};
|
||||
|
||||
typedef struct _emc_mr_data_t
|
||||
{
|
||||
u8 dev0_ch0;
|
||||
u8 dev0_ch1;
|
||||
u8 dev1_ch0;
|
||||
u8 dev1_ch1;
|
||||
} emc_mr_data_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -463,4 +463,54 @@
|
||||
#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0
|
||||
#define MC_DA_CONFIG0 0x9dc
|
||||
|
||||
// MC_SECURITY_CARVEOUTX_CFG0
|
||||
// Mode of LOCK_MODE.
|
||||
#define PROTECT_MODE_SHIFT 0
|
||||
#define SEC_CARVEOUT_CFG_SECURE (0 << PROTECT_MODE_SHIFT0)
|
||||
#define SEC_CARVEOUT_CFG_TZ_SECURE (1 << PROTECT_MODE_SHIFT0)
|
||||
// Enables PROTECT_MODE.
|
||||
#define LOCK_MODE_SHIFT 1
|
||||
#define SEC_CARVEOUT_CFG_UNLOCKED (0 << LOCK_MODE_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_LOCKED (1 << LOCK_MODE_SHIFT)
|
||||
|
||||
#define ADDRESS_TYPE_SHIFT 2
|
||||
#define SEC_CARVEOUT_CFG_ANY_ADDRESS (0 << ADDRESS_TYPE_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY (1 << ADDRESS_TYPE_SHIFT)
|
||||
|
||||
#define READ_ACCESS_LEVEL_SHIFT 3
|
||||
#define SEC_CARVEOUT_CFG_RD_ALL (1 << READ_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_RD_UNK (2 << READ_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_RD_FALCON_LS (4 << READ_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_RD_FALCON_HS (8 << READ_ACCESS_LEVEL_SHIFT)
|
||||
|
||||
#define WRITE_ACCESS_LEVEL_SHIFT 7
|
||||
#define SEC_CARVEOUT_CFG_WR_ALL (1 << WRITE_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_WR_UNK (2 << WRITE_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_WR_FALCON_LS (4 << WRITE_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_WR_FALCON_HS (8 << WRITE_ACCESS_LEVEL_SHIFT)
|
||||
|
||||
#define SEC_CARVEOUT_CFG_APERTURE_ID_MASK (3 << 11)
|
||||
|
||||
#define DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT 14
|
||||
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L0 (1 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L1 (2 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L2 (4 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L3 (8 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT)
|
||||
|
||||
#define DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT 18
|
||||
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L0 (1 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L1 (2 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L2 (4 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
|
||||
#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L3 (8 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT)
|
||||
|
||||
#define SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU (1 << 22)
|
||||
|
||||
#define SEC_CARVEOUT_CFG_TZ_GLOBAL_WR_EN_BYPASS_CHECK (1 << 23)
|
||||
#define SEC_CARVEOUT_CFG_TZ_GLOBAL_RD_EN_BYPASS_CHECK (1 << 24)
|
||||
|
||||
#define SEC_CARVEOUT_CFG_ALLOW_APERTURE_ID_MISMATCH (1 << 25)
|
||||
#define SEC_CARVEOUT_CFG_FORCE_APERTURE_ID_MATCH (1 << 26)
|
||||
|
||||
#define SEC_CARVEOUT_CFG_IS_WPR (1 << 27)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,7 @@ u32 minerva_init()
|
||||
memset(mtc_cfg, 0, sizeof(mtc_config_t));
|
||||
|
||||
// Set table to nyx storage.
|
||||
mtc_cfg->mtc_table = (emc_table_t *)&nyx_str->mtc_table;
|
||||
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
|
||||
|
||||
mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
|
||||
mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mc.h"
|
||||
#include "emc.h"
|
||||
#include "sdram_param_t210.h"
|
||||
@@ -29,7 +31,7 @@
|
||||
#include "../soc/t210.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
#define CONFIG_SDRAM_COMPRESS_CFG
|
||||
#define CONFIG_SDRAM_KEEP_ALIVE
|
||||
|
||||
#ifdef CONFIG_SDRAM_COMPRESS_CFG
|
||||
#include "../libs/compr/lz.h"
|
||||
@@ -40,13 +42,57 @@
|
||||
|
||||
static u32 _get_sdram_id()
|
||||
{
|
||||
u32 sdram_id = (fuse_read_odm(4) & 0x38) >> 3;
|
||||
return ((fuse_read_odm(4) & 0x38) >> 3);
|
||||
}
|
||||
|
||||
// Check if id is proper.
|
||||
if (sdram_id > 7)
|
||||
sdram_id = 0;
|
||||
static bool _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel)
|
||||
{
|
||||
bool err = true;
|
||||
|
||||
return sdram_id;
|
||||
for (s32 i = 0; i < EMC_STATUS_UPDATE_TIMEOUT; i++)
|
||||
{
|
||||
if (emc_channel)
|
||||
{
|
||||
if (emc_channel != 1)
|
||||
goto done;
|
||||
|
||||
if (((EMC_CH1(reg_offset) & bit_mask) != 0) == updated_state)
|
||||
{
|
||||
err = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (((EMC(reg_offset) & bit_mask) != 0) == updated_state)
|
||||
{
|
||||
err = false;
|
||||
break;
|
||||
}
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void _sdram_req_mrr_data(u32 data, bool dual_channel)
|
||||
{
|
||||
EMC(EMC_MRR) = data;
|
||||
_sdram_wait_emc_status(EMC_EMC_STATUS, EMC_STATUS_MRR_DIVLD, true, EMC_CHAN0);
|
||||
if (dual_channel)
|
||||
_sdram_wait_emc_status(EMC_EMC_STATUS, EMC_STATUS_MRR_DIVLD, true, EMC_CHAN1);
|
||||
}
|
||||
|
||||
emc_mr_data_t sdram_read_mrx(emc_mr_t mrx)
|
||||
{
|
||||
emc_mr_data_t data;
|
||||
_sdram_req_mrr_data((1 << 31) | (mrx << 16), EMC_CHAN0);
|
||||
data.dev0_ch0 = EMC(EMC_MRR) & 0xFF;
|
||||
data.dev0_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8);
|
||||
_sdram_req_mrr_data((1 << 30) | (mrx << 16), EMC_CHAN1);
|
||||
data.dev1_ch0 = EMC(EMC_MRR) & 0xFF;
|
||||
data.dev1_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void _sdram_config(const sdram_params_t *params)
|
||||
@@ -73,10 +119,14 @@ static void _sdram_config(const sdram_params_t *params)
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_MISC1) = params->pllm_setup_control;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_MISC2) = 0;
|
||||
|
||||
// u32 tmp = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20);
|
||||
// CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = tmp;
|
||||
// CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = tmp | 0x40000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | 0x40000000 | ((params->pllm_post_divider & 0xFFFF) << 20);
|
||||
#ifdef CONFIG_SDRAM_KEEP_ALIVE
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) =
|
||||
(params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20) | PLLCX_BASE_ENABLE;
|
||||
#else
|
||||
u32 pllm_div = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20);
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div | PLLCX_BASE_ENABLE;
|
||||
#endif
|
||||
|
||||
u32 wait_end = get_tmr_us() + 300;
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) & 0x8000000))
|
||||
@@ -91,7 +141,7 @@ break_nosleep:
|
||||
if (params->emc_clock_source_dll)
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = params->emc_clock_source_dll;
|
||||
if (params->clear_clock2_mc1)
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = 0x40000000;
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = 0x40000000; // Clear Reset to MC1.
|
||||
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x2000001; // Enable EMC and MEM clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x4000; // Enable EMC_DLL clock.
|
||||
@@ -509,9 +559,9 @@ break_nosleep:
|
||||
// ZQ CAL setup (not actually issuing ZQ CAL now).
|
||||
if (params->emc_zcal_warm_cold_boot_enables & 1)
|
||||
{
|
||||
if (params->memory_type == 2)
|
||||
if (params->memory_type == MEMORY_TYPE_DDR3L)
|
||||
EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt << 3;
|
||||
if (params->memory_type == 3)
|
||||
if (params->memory_type == MEMORY_TYPE_LPDDR4)
|
||||
{
|
||||
EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt;
|
||||
EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd;
|
||||
@@ -527,7 +577,7 @@ break_nosleep:
|
||||
|
||||
// Set clock enable signal.
|
||||
u32 pin_gpio_cfg = (params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12);
|
||||
if (params->memory_type == 2 || params->memory_type == 3)
|
||||
if (params->memory_type == MEMORY_TYPE_DDR3L || params->memory_type == MEMORY_TYPE_LPDDR4)
|
||||
{
|
||||
EMC(EMC_PIN) = pin_gpio_cfg;
|
||||
(void)EMC(EMC_PIN);
|
||||
@@ -536,9 +586,9 @@ break_nosleep:
|
||||
(void)EMC(EMC_PIN);
|
||||
}
|
||||
|
||||
if (params->memory_type == 3)
|
||||
if (params->memory_type == MEMORY_TYPE_LPDDR4)
|
||||
usleep(params->emc_pin_extra_wait + 2000);
|
||||
else if (params->memory_type == 2)
|
||||
else if (params->memory_type == MEMORY_TYPE_DDR3L)
|
||||
usleep(params->emc_pin_extra_wait + 500);
|
||||
|
||||
// Enable clock enable signal.
|
||||
@@ -547,15 +597,15 @@ break_nosleep:
|
||||
usleep(params->emc_pin_program_wait);
|
||||
|
||||
// Send NOP (trigger just needs to be non-zero).
|
||||
if (params->memory_type != 3)
|
||||
if (params->memory_type != MEMORY_TYPE_LPDDR4)
|
||||
EMC(EMC_NOP) = (params->emc_dev_select << 30) + 1;
|
||||
|
||||
// On coldboot w/LPDDR2/3, wait 200 uSec after asserting CKE high.
|
||||
if (params->memory_type == 1)
|
||||
if (params->memory_type == MEMORY_TYPE_LPDDR2)
|
||||
usleep(params->emc_pin_extra_wait + 200);
|
||||
|
||||
// Init zq calibration,
|
||||
if (params->memory_type == 3)
|
||||
if (params->memory_type == MEMORY_TYPE_LPDDR4)
|
||||
{
|
||||
// Patch 6 using BCT spare variables.
|
||||
if (params->emc_bct_spare10)
|
||||
@@ -596,7 +646,7 @@ break_nosleep:
|
||||
PMC(APBDEV_PMC_DDR_CFG) = params->pmc_ddr_cfg;
|
||||
|
||||
// Start periodic ZQ calibration (LPDDRx only).
|
||||
if (params->memory_type - 1 <= 2)
|
||||
if (params->memory_type && params->memory_type <= MEMORY_TYPE_LPDDR4)
|
||||
{
|
||||
EMC(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval;
|
||||
EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt;
|
||||
@@ -641,18 +691,47 @@ break_nosleep:
|
||||
MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access;
|
||||
MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl;
|
||||
|
||||
//Disable write access to a bunch of EMC registers.
|
||||
// Disable write access to a bunch of EMC registers.
|
||||
MC(MC_EMEM_CFG_ACCESS_CTRL) = 1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SDRAM_COMPRESS_CFG
|
||||
static void _sdram_patch_model_params(u32 dramid, u32 *params)
|
||||
{
|
||||
for (u32 i = 0; i < sizeof(sdram_cfg_vendor_patches) / sizeof(sdram_vendor_patch_t); i++)
|
||||
if (sdram_cfg_vendor_patches[i].dramid & DRAM_ID(dramid))
|
||||
params[sdram_cfg_vendor_patches[i].addr] = sdram_cfg_vendor_patches[i].val;
|
||||
}
|
||||
#endif
|
||||
|
||||
sdram_params_t *sdram_get_params()
|
||||
{
|
||||
// Check if id is proper.
|
||||
u32 dramid = _get_sdram_id();
|
||||
if (dramid > 6)
|
||||
dramid = 0;
|
||||
|
||||
#ifdef CONFIG_SDRAM_COMPRESS_CFG
|
||||
u8 *buf = (u8 *)SDRAM_PARAMS_ADDR;
|
||||
LZ_Uncompress(_dram_cfg_lz, buf, sizeof(_dram_cfg_lz));
|
||||
return (sdram_params_t *)&buf[sizeof(sdram_params_t) * _get_sdram_id()];
|
||||
return (sdram_params_t *)&buf[sizeof(sdram_params_t) * dramid];
|
||||
#else
|
||||
return _dram_cfgs[_get_sdram_id()];
|
||||
sdram_params_t *buf = (sdram_params_t *)SDRAM_PARAMS_ADDR;
|
||||
memcpy(buf, &_dram_cfg_0_samsung_4gb, sizeof(sdram_params_t));
|
||||
switch (dramid)
|
||||
{
|
||||
case DRAM_4GB_SAMSUNG_K4F6E304HB_MGCH:
|
||||
case DRAM_4GB_MICRON_MT53B512M32D2NP_062_WT:
|
||||
break;
|
||||
case DRAM_4GB_HYNIX_H9HCNNNBPUMLHR_NLN:
|
||||
case DRAM_4GB_COPPER_UNK_3:
|
||||
case DRAM_6GB_SAMSUNG_K4FHE3D4HM_MFCH:
|
||||
case DRAM_4GB_COPPER_UNK_5:
|
||||
case DRAM_4GB_COPPER_UNK_6:
|
||||
_sdram_patch_model_params(dramid, (u32 *)buf);
|
||||
break;
|
||||
}
|
||||
return buf;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
#ifndef _SDRAM_H_
|
||||
#define _SDRAM_H_
|
||||
|
||||
#include "emc.h"
|
||||
#include "sdram_param_t210.h"
|
||||
|
||||
void sdram_init();
|
||||
sdram_params_t *sdram_get_params();
|
||||
sdram_params_t *sdram_get_params_patched();
|
||||
void sdram_lp0_save_params(const void *params);
|
||||
emc_mr_data_t sdram_read_mrx(emc_mr_t mrx);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,12 +26,12 @@
|
||||
#ifndef _SDRAM_PARAM_T210_H_
|
||||
#define _SDRAM_PARAM_T210_H_
|
||||
|
||||
#define MEMORY_TYPE_NONE 0
|
||||
#define MEMORY_TYPE_DDR 0
|
||||
#define MEMORY_TYPE_LPDDR 0
|
||||
#define MEMORY_TYPE_DDR2 0
|
||||
#define MEMORY_TYPE_NONE 0
|
||||
#define MEMORY_TYPE_DDR 0
|
||||
#define MEMORY_TYPE_LPDDR 0
|
||||
#define MEMORY_TYPE_DDR2 0
|
||||
#define MEMORY_TYPE_LPDDR2 1
|
||||
#define MEMORY_TYPE_DDR3 2
|
||||
#define MEMORY_TYPE_DDR3L 2
|
||||
#define MEMORY_TYPE_LPDDR4 3
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,7 @@ int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
|
||||
case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
|
||||
data = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_InputSource);
|
||||
data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3;
|
||||
*value = 0;
|
||||
*value += ((data >> 0) & 1) ? 80 : 0;
|
||||
*value += ((data >> 1) & 1) ? 160 : 0;
|
||||
*value += ((data >> 2) & 1) ? 320 : 0;
|
||||
@@ -77,6 +78,7 @@ int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
|
||||
case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA).
|
||||
data = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_ChrgCurr);
|
||||
data = (data & BQ24193_CHRGCURR_ICHG_MASK) >> 2;
|
||||
*value = 0;
|
||||
*value += ((data >> 0) & 1) ? 64 : 0;
|
||||
*value += ((data >> 1) & 1) ? 128 : 0;
|
||||
*value += ((data >> 2) & 1) ? 256 : 0;
|
||||
@@ -92,6 +94,7 @@ int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
|
||||
case BQ24193_ChargeVoltageLimit: // Charge voltage limit (mV).
|
||||
data = i2c_recv_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_ChrgVolt);
|
||||
data = (data & BQ24193_CHRGVOLT_VREG) >> 2;
|
||||
*value = 0;
|
||||
*value += ((data >> 0) & 1) ? 16 : 0;
|
||||
*value += ((data >> 1) & 1) ? 32 : 0;
|
||||
*value += ((data >> 2) & 1) ? 64 : 0;
|
||||
|
||||
@@ -46,6 +46,12 @@
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
static u32 battery_voltage = 0;
|
||||
u32 max17050_get_cached_batt_volt()
|
||||
{
|
||||
return battery_voltage;
|
||||
}
|
||||
|
||||
int max17050_get_property(enum MAX17050_reg reg, int *value)
|
||||
{
|
||||
u16 data;
|
||||
@@ -74,6 +80,7 @@ int max17050_get_property(enum MAX17050_reg reg, int *value)
|
||||
case MAX17050_VCELL: // Voltage now.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_VCELL);
|
||||
*value = data * 625 / 8 / 1000;
|
||||
battery_voltage = *value;
|
||||
break;
|
||||
case MAX17050_AvgVCELL: // Voltage avg.
|
||||
i2c_recv_buf_small((u8 *)&data, 2, I2C_1, MAXIM17050_I2C_ADDR, MAX17050_AvgVCELL);
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#ifndef __MAX17050_H_
|
||||
#define __MAX17050_H_
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
#define MAX17050_STATUS_BattAbsent (1 << 3)
|
||||
#define MAX17050_DEFAULT_SNS_RESISTOR 10000
|
||||
|
||||
@@ -128,5 +130,6 @@ enum MAX17050_reg {
|
||||
|
||||
int max17050_get_property(enum MAX17050_reg reg, int *value);
|
||||
int max17050_fix_configuration();
|
||||
u32 max17050_get_cached_batt_volt();
|
||||
|
||||
#endif /* __MAX17050_H_ */
|
||||
|
||||
@@ -35,10 +35,10 @@ void max77620_rtc_get_time(rtc_time_t *time)
|
||||
// Get time.
|
||||
time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F;
|
||||
time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F;
|
||||
u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG);
|
||||
time->hour = hour & 0x1F;
|
||||
|
||||
time->hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG) & 0x1F;
|
||||
|
||||
if (!(val & MAX77620_RTC_24H) && time->hour & MAX77620_RTC_HOUR_PM_MASK)
|
||||
if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK))
|
||||
time->hour = (time->hour & 0xF) + 12;
|
||||
|
||||
// Get day of week. 1: Monday to 7: Sunday.
|
||||
|
||||
@@ -195,6 +195,24 @@ int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src,
|
||||
return _se_execute(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)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = 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_PREVAHB) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = 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_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||
}
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
return _se_execute(OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -275,7 +293,6 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u
|
||||
return 1;
|
||||
}
|
||||
|
||||
// se_calc_sha256() was derived from Atmosphère's se_calculate_sha256.
|
||||
int se_calc_sha256(void *dst, const void *src, u32 src_size)
|
||||
{
|
||||
int res;
|
||||
@@ -302,3 +319,76 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size)
|
||||
return res;
|
||||
}
|
||||
|
||||
int se_gen_prng128(void *dst)
|
||||
{
|
||||
// Setup config for X931 PRNG.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | 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_NORMAL);
|
||||
//SE(SE_RNG_SRC_CONFIG_REG_OFFSET) =
|
||||
// SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) | SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
|
||||
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 1;
|
||||
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (16 >> 4) - 1;
|
||||
|
||||
// Trigger the operation.
|
||||
return _se_execute(OP_START, dst, 16, NULL, 0);
|
||||
}
|
||||
|
||||
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
{
|
||||
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
|
||||
|
||||
// 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_CRYPTO_REG_OFFSET) = 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_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute(OP_START, NULL, 0, NULL, 0);
|
||||
|
||||
// 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);
|
||||
|
||||
for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++)
|
||||
{
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3);
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
||||
memcpy(keys + i * keysize, aligned_buf, 0x10);
|
||||
|
||||
if (keysize > 0x10)
|
||||
{
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7);
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
||||
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
// Save SRK to PMC secure scratches.
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK);
|
||||
SE(0x80) = 0; // SE_CRYPTO_LAST_BLOCK
|
||||
_se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
|
||||
// End context save.
|
||||
SE(SE_CONFIG_REG_OFFSET) = 0;
|
||||
_se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
|
||||
// Get SRK.
|
||||
u32 srk[4];
|
||||
srk[0] = PMC(0xC0);
|
||||
srk[1] = PMC(0xC4);
|
||||
srk[2] = PMC(0x224);
|
||||
srk[3] = PMC(0x228);
|
||||
|
||||
// Decrypt context.
|
||||
se_aes_key_clear(3);
|
||||
se_aes_key_set(3, srk, 0x10);
|
||||
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize);
|
||||
se_aes_key_clear(3);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
void se_rsa_acc_ctrl(u32 rs, u32 flags);
|
||||
void se_key_acc_ctrl(u32 ks, u32 flags);
|
||||
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
|
||||
void se_aes_key_set(u32 ks, void *key, u32 size);
|
||||
void se_aes_key_clear(u32 ks);
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
|
||||
@@ -28,5 +29,6 @@ int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, 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_calc_sha256(void *dst, const void *src, u32 src_size);
|
||||
int se_gen_prng128(void *dst);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -70,27 +70,26 @@
|
||||
#define SE_CONFIG_DEC_MODE(x) (x << SE_CONFIG_DEC_MODE_SHIFT)
|
||||
|
||||
#define SE_RNG_CONFIG_REG_OFFSET 0x340
|
||||
#define DRBG_MODE_SHIFT 0
|
||||
#define DRBG_MODE_NORMAL 0
|
||||
#define DRBG_MODE_FORCE_INSTANTION 1
|
||||
#define DRBG_MODE_FORCE_RESEED 2
|
||||
#define SE_RNG_CONFIG_MODE(x) (x << DRBG_MODE_SHIFT)
|
||||
#define RNG_MODE_SHIFT 0
|
||||
#define RNG_MODE_NORMAL 0
|
||||
#define RNG_MODE_FORCE_INSTANTION 1
|
||||
#define RNG_MODE_FORCE_RESEED 2
|
||||
#define SE_RNG_CONFIG_MODE(x) (x << RNG_MODE_SHIFT)
|
||||
#define RNG_SRC_SHIFT 2
|
||||
#define RNG_SRC_NONE 0
|
||||
#define RNG_SRC_ENTROPY 1
|
||||
#define RNG_SRC_LFSR 2
|
||||
#define SE_RNG_CONFIG_SRC(x) (x << RNG_SRC_SHIFT)
|
||||
|
||||
#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344
|
||||
#define DRBG_RO_ENT_SRC_SHIFT 1
|
||||
#define DRBG_RO_ENT_SRC_ENABLE 1
|
||||
#define DRBG_RO_ENT_SRC_DISABLE 0
|
||||
#define SE_RNG_SRC_CONFIG_RO_ENT_SRC(x) (x << DRBG_RO_ENT_SRC_SHIFT)
|
||||
#define DRBG_RO_ENT_SRC_LOCK_SHIFT 0
|
||||
#define DRBG_RO_ENT_SRC_LOCK_ENABLE 1
|
||||
#define DRBG_RO_ENT_SRC_LOCK_DISABLE 0
|
||||
#define SE_RNG_SRC_CONFIG_RO_ENT_SRC_LOCK(x) (x << DRBG_RO_ENT_SRC_LOCK_SHIFT)
|
||||
|
||||
#define DRBG_SRC_SHIFT 2
|
||||
#define DRBG_SRC_NONE 0
|
||||
#define DRBG_SRC_ENTROPY 1
|
||||
#define DRBG_SRC_LFSR 2
|
||||
#define SE_RNG_CONFIG_SRC(x) (x << DRBG_SRC_SHIFT)
|
||||
#define RNG_SRC_RO_ENT_SHIFT 1
|
||||
#define RNG_SRC_RO_ENT_ENABLE 1
|
||||
#define RNG_SRC_RO_ENT_DISABLE 0
|
||||
#define SE_RNG_SRC_CONFIG_ENT_SRC(x) (x << RNG_SRC_RO_ENT_SHIFT)
|
||||
#define RNG_SRC_RO_ENT_LOCK_SHIFT 0
|
||||
#define RNG_SRC_RO_ENT_LOCK_ENABLE 1
|
||||
#define RNG_SRC_RO_ENT_LOCK_DISABLE 0
|
||||
#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) (x << RNG_SRC_RO_ENT_LOCK_SHIFT)
|
||||
|
||||
#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348
|
||||
|
||||
@@ -119,6 +118,8 @@
|
||||
#define OP_DONE 1
|
||||
#define SE_OP_DONE(x, y) ((x) && (y << SE_OP_DONE_SHIFT))
|
||||
|
||||
#define SE_CRYPTO_LAST_BLOCK 0x080
|
||||
|
||||
#define SE_CRYPTO_REG_OFFSET 0x304
|
||||
#define SE_CRYPTO_HASH_SHIFT 0
|
||||
#define HASH_DISABLE 0
|
||||
@@ -191,6 +192,7 @@
|
||||
#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
|
||||
|
||||
@@ -89,6 +89,10 @@ static clock_t _clock_pwm = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 17, 6, 4 // Fref: 6.2MHz.
|
||||
};
|
||||
|
||||
static clock_t _clock_sdmmc_legacy_tm = {
|
||||
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, 1, 4, 66
|
||||
};
|
||||
|
||||
void clock_enable(const clock_t *clk)
|
||||
{
|
||||
// Put clock into reset.
|
||||
@@ -124,6 +128,29 @@ void clock_enable_uart(u32 idx)
|
||||
clock_enable(&_clock_uart[idx]);
|
||||
}
|
||||
|
||||
void clock_disable_uart(u32 idx)
|
||||
{
|
||||
clock_disable(&_clock_uart[idx]);
|
||||
}
|
||||
|
||||
#define UART_SRC_CLK_DIV_EN (1 << 24)
|
||||
|
||||
int clock_uart_use_src_div(u32 idx, u32 baud)
|
||||
{
|
||||
u32 clk_src_div = CLOCK(_clock_uart[idx].source) & 0xE0000000;
|
||||
|
||||
if (baud == 1000000)
|
||||
CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 49;
|
||||
else
|
||||
{
|
||||
CLOCK(_clock_uart[idx].source) = clk_src_div | 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clock_enable_i2c(u32 idx)
|
||||
{
|
||||
clock_enable(&_clock_i2c[idx]);
|
||||
@@ -258,10 +285,10 @@ void clock_enable_pllc(u32 divn)
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ;
|
||||
usleep(10);
|
||||
|
||||
// Set PLLC4 dividers.
|
||||
// Set PLLC dividers.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = (divn << 10) | 4; // DIVM: 4, DIVP: 1.
|
||||
|
||||
// Enable PLLC4 and wait for Phase and Frequency lock.
|
||||
// Enable PLLC and wait for Phase and Frequency lock.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_ENABLE;
|
||||
while (!(CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLLCX_BASE_LOCK))
|
||||
;
|
||||
@@ -423,56 +450,78 @@ static void _clock_sdmmc_clear_enable(u32 id)
|
||||
}
|
||||
}
|
||||
|
||||
static u32 _clock_sdmmc_table[8] = { 0 };
|
||||
static void _clock_sdmmc_config_legacy_tm()
|
||||
{
|
||||
clock_t *clk = &_clock_sdmmc_legacy_tm;
|
||||
if (!(CLOCK(clk->enable) & (1 << clk->index)))
|
||||
clock_enable(clk);
|
||||
}
|
||||
|
||||
#define PLLP_OUT0 0x0
|
||||
static int _clock_sdmmc_config_clock_host(u32 *pout, u32 id, u32 val)
|
||||
typedef struct _clock_sdmmc_t
|
||||
{
|
||||
u32 clock;
|
||||
u32 real_clock;
|
||||
} clock_sdmmc_t;
|
||||
|
||||
static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 };
|
||||
|
||||
#define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0
|
||||
#define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3
|
||||
#define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1
|
||||
|
||||
static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
|
||||
{
|
||||
u32 divisor = 0;
|
||||
u32 source = PLLP_OUT0;
|
||||
u32 source = SDMMC_CLOCK_SRC_PLLP_OUT0;
|
||||
|
||||
if (id > SDMMC_4)
|
||||
return 0;
|
||||
|
||||
// Get IO clock divisor.
|
||||
switch (val)
|
||||
{
|
||||
case 25000:
|
||||
*pout = 24728;
|
||||
*pclock = 24728;
|
||||
divisor = 31; // 16.5 div.
|
||||
break;
|
||||
case 26000:
|
||||
*pout = 25500;
|
||||
*pclock = 25500;
|
||||
divisor = 30; // 16 div.
|
||||
break;
|
||||
case 40800:
|
||||
*pout = 40800;
|
||||
*pclock = 40800;
|
||||
divisor = 18; // 10 div.
|
||||
break;
|
||||
case 50000:
|
||||
*pout = 48000;
|
||||
*pclock = 48000;
|
||||
divisor = 15; // 8.5 div.
|
||||
break;
|
||||
case 52000:
|
||||
*pout = 51000;
|
||||
*pclock = 51000;
|
||||
divisor = 14; // 8 div.
|
||||
break;
|
||||
case 100000:
|
||||
*pout = 90667;
|
||||
*pclock = 90667;
|
||||
divisor = 7; // 4.5 div.
|
||||
break;
|
||||
case 200000:
|
||||
*pout = 163200;
|
||||
case 164000:
|
||||
*pclock = 163200;
|
||||
divisor = 3; // 2.5 div.
|
||||
break;
|
||||
case 208000:
|
||||
*pout = 204000;
|
||||
case 200000:
|
||||
*pclock = 204000;
|
||||
divisor = 2; // 2 div.
|
||||
break;
|
||||
default:
|
||||
*pout = 24728;
|
||||
*pclock = 24728;
|
||||
divisor = 31; // 16.5 div.
|
||||
}
|
||||
|
||||
_clock_sdmmc_table[2 * id] = val;
|
||||
_clock_sdmmc_table[2 * id + 1] = *pout;
|
||||
_clock_sdmmc_table[id].clock = val;
|
||||
_clock_sdmmc_table[id].real_clock = *pclock;
|
||||
|
||||
// Set SDMMC legacy timeout clock.
|
||||
_clock_sdmmc_config_legacy_tm();
|
||||
|
||||
// Set SDMMC clock.
|
||||
switch (id)
|
||||
@@ -494,70 +543,75 @@ static int _clock_sdmmc_config_clock_host(u32 *pout, u32 id, u32 val)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val)
|
||||
void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val)
|
||||
{
|
||||
if (_clock_sdmmc_table[2 * id] == val)
|
||||
if (_clock_sdmmc_table[id].clock == val)
|
||||
{
|
||||
*pout = _clock_sdmmc_table[2 * id + 1];
|
||||
*pclock = _clock_sdmmc_table[id].real_clock;
|
||||
}
|
||||
else
|
||||
{
|
||||
int is_enabled = _clock_sdmmc_is_enabled(id);
|
||||
if (is_enabled)
|
||||
_clock_sdmmc_clear_enable(id);
|
||||
_clock_sdmmc_config_clock_host(pout, id, val);
|
||||
_clock_sdmmc_config_clock_host(pclock, id, val);
|
||||
if (is_enabled)
|
||||
_clock_sdmmc_set_enable(id);
|
||||
_clock_sdmmc_is_reset(id);
|
||||
}
|
||||
}
|
||||
|
||||
void clock_sdmmc_get_card_clock_div(u32 *pout, u16 *pdivisor, u32 type)
|
||||
void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type)
|
||||
{
|
||||
// Get Card clock divisor.
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
*pout = 26000;
|
||||
case SDHCI_TIMING_MMC_ID: // Actual IO Freq: 380.59 KHz.
|
||||
*pclock = 26000;
|
||||
*pdivisor = 66;
|
||||
break;
|
||||
case 1:
|
||||
*pout = 26000;
|
||||
case SDHCI_TIMING_MMC_LS26:
|
||||
*pclock = 26000;
|
||||
*pdivisor = 1;
|
||||
break;
|
||||
case 2:
|
||||
*pout = 52000;
|
||||
case SDHCI_TIMING_MMC_HS52:
|
||||
*pclock = 52000;
|
||||
*pdivisor = 1;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 11:
|
||||
*pout = 200000;
|
||||
case SDHCI_TIMING_MMC_HS200:
|
||||
case SDHCI_TIMING_MMC_HS400:
|
||||
case SDHCI_TIMING_UHS_SDR104:
|
||||
*pclock = 200000;
|
||||
*pdivisor = 1;
|
||||
break;
|
||||
case 5:
|
||||
*pout = 25000;
|
||||
case SDHCI_TIMING_SD_ID: // Actual IO Freq: 380.43 KHz.
|
||||
*pclock = 25000;
|
||||
*pdivisor = 64;
|
||||
break;
|
||||
case 6:
|
||||
case 8:
|
||||
*pout = 25000;
|
||||
case SDHCI_TIMING_SD_DS12:
|
||||
case SDHCI_TIMING_UHS_SDR12:
|
||||
*pclock = 25000;
|
||||
*pdivisor = 1;
|
||||
break;
|
||||
case 7:
|
||||
*pout = 50000;
|
||||
case SDHCI_TIMING_SD_HS25:
|
||||
case SDHCI_TIMING_UHS_SDR25:
|
||||
*pclock = 50000;
|
||||
*pdivisor = 1;
|
||||
break;
|
||||
case 10:
|
||||
*pout = 100000;
|
||||
case SDHCI_TIMING_UHS_SDR50:
|
||||
*pclock = 100000;
|
||||
*pdivisor = 1;
|
||||
break;
|
||||
case 13:
|
||||
*pout = 40800;
|
||||
case SDHCI_TIMING_UHS_SDR82:
|
||||
*pclock = 164000;
|
||||
*pdivisor = 1;
|
||||
break;
|
||||
case 14:
|
||||
*pout = 200000;
|
||||
case SDHCI_TIMING_UHS_DDR50:
|
||||
*pclock = 40800;
|
||||
*pdivisor = 1;
|
||||
break;
|
||||
case SDHCI_TIMING_MMC_DDR52: // Actual IO Freq: 49.92 MHz.
|
||||
*pclock = 200000;
|
||||
*pdivisor = 2;
|
||||
break;
|
||||
}
|
||||
@@ -570,15 +624,15 @@ int clock_sdmmc_is_not_reset_and_enabled(u32 id)
|
||||
|
||||
void clock_sdmmc_enable(u32 id, u32 val)
|
||||
{
|
||||
u32 div = 0;
|
||||
u32 clock = 0;
|
||||
|
||||
if (_clock_sdmmc_is_enabled(id))
|
||||
_clock_sdmmc_clear_enable(id);
|
||||
_clock_sdmmc_set_reset(id);
|
||||
_clock_sdmmc_config_clock_host(&div, id, val);
|
||||
_clock_sdmmc_config_clock_host(&clock, id, val);
|
||||
_clock_sdmmc_set_enable(id);
|
||||
_clock_sdmmc_is_reset(id);
|
||||
usleep((100000 + div - 1) / div);
|
||||
usleep((100000 + clock - 1) / clock);
|
||||
_clock_sdmmc_clear_reset(id);
|
||||
_clock_sdmmc_is_reset(id);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,12 @@
|
||||
#define CLK_RST_CONTROLLER_PLLM_MISC1 0x98
|
||||
#define CLK_RST_CONTROLLER_PLLM_MISC2 0x9C
|
||||
#define CLK_RST_CONTROLLER_PLLP_BASE 0xA0
|
||||
#define CLK_RST_CONTROLLER_PLLA_BASE 0xB0
|
||||
#define CLK_RST_CONTROLLER_PLLA_OUT 0xB4
|
||||
#define CLK_RST_CONTROLLER_PLLA_MISC1 0xB8
|
||||
#define CLK_RST_CONTROLLER_PLLA_MISC 0xBC
|
||||
#define CLK_RST_CONTROLLER_PLLU_BASE 0xC0
|
||||
#define CLK_RST_CONTROLLER_PLLU_MISC 0xCC
|
||||
#define CLK_RST_CONTROLLER_PLLD_BASE 0xD0
|
||||
#define CLK_RST_CONTROLLER_PLLD_MISC1 0xD8
|
||||
#define CLK_RST_CONTROLLER_PLLD_MISC 0xDC
|
||||
@@ -52,6 +58,7 @@
|
||||
#define CLK_RST_CONTROLLER_PLLE_MISC 0xEC
|
||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA 0xF8
|
||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB 0xFC
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2S2 0x100
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_PWM 0x110
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 0x124
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 0x128
|
||||
@@ -70,6 +77,7 @@
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 0x1BC
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTD 0x1C0
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_CSITE 0x1D4
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2S1 0x1D8
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_TSEC 0x1F4
|
||||
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_X 0x280
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_X_SET 0x284
|
||||
@@ -104,20 +112,27 @@
|
||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3A4
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 0x3C4
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1 0x3EC
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SYS 0x400
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_V_SET 0x430
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_V_CLR 0x434
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_W_SET 0x438
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_W_CLR 0x43C
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_V_SET 0x440
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_V_CLR 0x444
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_W_SET 0x448
|
||||
#define CLK_RST_CONTROLLER_CLK_ENB_W_CLR 0x44C
|
||||
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET 0x450
|
||||
#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR 0x454
|
||||
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG0 0x480
|
||||
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG1 0x484
|
||||
#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG2 0x488
|
||||
#define CLK_RST_CONTROLLER_PLLE_AUX 0x48C
|
||||
#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S0 0x4A0
|
||||
#define CLK_RST_CONTROLLER_PLLX_MISC_3 0x518
|
||||
#define CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0 0x52C
|
||||
#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE 0x554
|
||||
#define CLK_RST_CONTROLLER_SPARE_REG0 0x55C
|
||||
#define CLK_RST_CONTROLLER_PLLC4_BASE 0x5A4
|
||||
@@ -131,6 +146,7 @@
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL 0x66C
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK 0x6CC
|
||||
#define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704
|
||||
#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710
|
||||
|
||||
@@ -141,6 +157,10 @@
|
||||
#define PLLCX_BASE_REF_DIS (1 << 29)
|
||||
#define PLLCX_BASE_LOCK (1 << 27)
|
||||
|
||||
#define PLLA_BASE_IDDQ (1 << 25)
|
||||
#define PLLA_OUT0_CLKEN (1 << 1)
|
||||
#define PLLA_OUT0_RSTN_CLR (1 << 0)
|
||||
|
||||
#define PLLC_MISC_RESET (1 << 30)
|
||||
#define PLLC_MISC1_IDDQ (1 << 27)
|
||||
#define PLLC_OUT1_CLKEN (1 << 1)
|
||||
@@ -169,6 +189,8 @@ void clock_disable(const clock_t *clk);
|
||||
/*! Clock control for specific hardware portions. */
|
||||
void clock_enable_fuse(bool enable);
|
||||
void clock_enable_uart(u32 idx);
|
||||
void clock_disable_uart(u32 idx);
|
||||
int clock_uart_use_src_div(u32 idx, u32 baud);
|
||||
void clock_enable_i2c(u32 idx);
|
||||
void clock_disable_i2c(u32 idx);
|
||||
void clock_enable_se();
|
||||
@@ -193,8 +215,8 @@ void clock_enable_pwm();
|
||||
void clock_disable_pwm();
|
||||
void clock_enable_pllc(u32 divn);
|
||||
void clock_disable_pllc();
|
||||
void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val);
|
||||
void clock_sdmmc_get_card_clock_div(u32 *pout, u16 *pdivisor, u32 type);
|
||||
void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val);
|
||||
void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type);
|
||||
int clock_sdmmc_is_not_reset_and_enabled(u32 id);
|
||||
void clock_sdmmc_enable(u32 id, u32 val);
|
||||
void clock_sdmmc_disable(u32 id);
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#define FUSE_PRIVATE_KEY3 0x1B0
|
||||
#define FUSE_PRIVATE_KEY4 0x1B4
|
||||
#define FUSE_RESERVED_SW 0x1C0
|
||||
#define FUSE_USB_CALIB 0x1F0
|
||||
#define FUSE_SKU_DIRECT_CONFIG 0x1F4
|
||||
#define FUSE_OPT_VENDOR_CODE 0x200
|
||||
#define FUSE_OPT_FAB_CODE 0x204
|
||||
@@ -63,6 +64,7 @@
|
||||
#define FUSE_OPT_X_COORDINATE 0x214
|
||||
#define FUSE_OPT_Y_COORDINATE 0x218
|
||||
#define FUSE_GPU_IDDQ_CALIB 0x228
|
||||
#define FUSE_USB_CALIB_EXT 0x350
|
||||
|
||||
/*! Fuse commands. */
|
||||
#define FUSE_READ 0x1
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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,
|
||||
@@ -14,81 +15,146 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../soc/gpio.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "gpio.h"
|
||||
#include "irq.h"
|
||||
#include "t210.h"
|
||||
|
||||
static const u16 _gpio_cnf[31] = {
|
||||
0x000, 0x004, 0x008, 0x00C,
|
||||
0x100, 0x104, 0x108, 0x10C,
|
||||
0x200, 0x204, 0x208, 0x20C,
|
||||
0x300, 0x304, 0x308, 0x30C,
|
||||
0x400, 0x404, 0x408, 0x40C,
|
||||
0x500, 0x504, 0x508, 0x50C,
|
||||
0x600, 0x604, 0x608, 0x60C,
|
||||
0x700, 0x704, 0x708
|
||||
};
|
||||
#define GPIO_BANK_IDX(port) (port >> 2)
|
||||
|
||||
static const u16 _gpio_oe[31] = {
|
||||
0x010, 0x014, 0x018, 0x01C,
|
||||
0x110, 0x114, 0x118, 0x11C,
|
||||
0x210, 0x214, 0x218, 0x21C,
|
||||
0x310, 0x314, 0x318, 0x31C,
|
||||
0x410, 0x414, 0x418, 0x41C,
|
||||
0x510, 0x514, 0x518, 0x51C,
|
||||
0x610, 0x614, 0x618, 0x61C,
|
||||
0x710, 0x714, 0x718
|
||||
};
|
||||
#define GPIO_CNF_OFFSET(port) (0x00 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_OE_OFFSET(port) (0x10 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_OUT_OFFSET(port) (0x20 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_IN_OFFSET(port) (0x30 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_INT_STA_OFFSET(port) (0x40 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_INT_ENB_OFFSET(port) (0x50 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_INT_LVL_OFFSET(port) (0x60 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_INT_CLR_OFFSET(port) (0x70 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
|
||||
static const u16 _gpio_out[31] = {
|
||||
0x020, 0x024, 0x028, 0x02C,
|
||||
0x120, 0x124, 0x128, 0x12C,
|
||||
0x220, 0x224, 0x228, 0x22C,
|
||||
0x320, 0x324, 0x328, 0x32C,
|
||||
0x420, 0x424, 0x428, 0x42C,
|
||||
0x520, 0x524, 0x528, 0x52C,
|
||||
0x620, 0x624, 0x628, 0x62C,
|
||||
0x720, 0x724, 0x728
|
||||
};
|
||||
#define GPIO_CNF_MASKED_OFFSET(port) (0x80 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_OE_MASKED_OFFSET(port) (0x90 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
#define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + ((port >> 2) << 8) + ((port % 4) << 2))
|
||||
|
||||
static const u16 _gpio_in[31] = {
|
||||
0x030, 0x034, 0x038, 0x03C,
|
||||
0x130, 0x134, 0x138, 0x13C,
|
||||
0x230, 0x234, 0x238, 0x23C,
|
||||
0x330, 0x334, 0x338, 0x33C,
|
||||
0x430, 0x434, 0x438, 0x43C,
|
||||
0x530, 0x534, 0x538, 0x53C,
|
||||
0x630, 0x634, 0x638, 0x63C,
|
||||
0x730, 0x734, 0x738
|
||||
static u8 gpio_bank_irq_ids[8] = {
|
||||
IRQ_GPIO1, IRQ_GPIO2, IRQ_GPIO3, IRQ_GPIO4,
|
||||
IRQ_GPIO5, IRQ_GPIO6, IRQ_GPIO7, IRQ_GPIO8
|
||||
};
|
||||
|
||||
void gpio_config(u32 port, u32 pins, int mode)
|
||||
{
|
||||
u32 offset = GPIO_CNF_OFFSET(port);
|
||||
|
||||
if (mode)
|
||||
GPIO(_gpio_cnf[port]) |= pins;
|
||||
GPIO(offset) |= pins;
|
||||
else
|
||||
GPIO(_gpio_cnf[port]) &= ~pins;
|
||||
(void)GPIO(_gpio_cnf[port]);
|
||||
GPIO(offset) &= ~pins;
|
||||
|
||||
(void)GPIO(offset); // Commit the write.
|
||||
}
|
||||
|
||||
void gpio_output_enable(u32 port, u32 pins, int enable)
|
||||
{
|
||||
u32 port_offset = GPIO_OE_OFFSET(port);
|
||||
|
||||
if (enable)
|
||||
GPIO(_gpio_oe[port]) |= pins;
|
||||
GPIO(port_offset) |= pins;
|
||||
else
|
||||
GPIO(_gpio_oe[port]) &= ~pins;
|
||||
(void)GPIO(_gpio_oe[port]);
|
||||
GPIO(port_offset) &= ~pins;
|
||||
|
||||
(void)GPIO(port_offset); // Commit the write.
|
||||
}
|
||||
|
||||
void gpio_write(u32 port, u32 pins, int high)
|
||||
{
|
||||
u32 port_offset = GPIO_OUT_OFFSET(port);
|
||||
|
||||
if (high)
|
||||
GPIO(_gpio_out[port]) |= pins;
|
||||
GPIO(port_offset) |= pins;
|
||||
else
|
||||
GPIO(_gpio_out[port]) &= ~pins;
|
||||
(void)GPIO(_gpio_out[port]);
|
||||
GPIO(port_offset) &= ~pins;
|
||||
|
||||
(void)GPIO(port_offset); // Commit the write.
|
||||
}
|
||||
|
||||
int gpio_read(u32 port, u32 pins)
|
||||
{
|
||||
return (GPIO(_gpio_in[port]) & pins) ? 1 : 0;
|
||||
u32 port_offset = GPIO_IN_OFFSET(port);
|
||||
|
||||
return (GPIO(port_offset) & pins) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void _gpio_interrupt_clear(u32 port, u32 pins)
|
||||
{
|
||||
u32 port_offset = GPIO_INT_CLR_OFFSET(port);
|
||||
|
||||
GPIO(port_offset) |= pins;
|
||||
|
||||
(void)GPIO(port_offset); // Commit the write.
|
||||
}
|
||||
|
||||
int gpio_interrupt_status(u32 port, u32 pins)
|
||||
{
|
||||
u32 port_offset = GPIO_INT_STA_OFFSET(port);
|
||||
u32 enabled = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins;
|
||||
|
||||
int status = ((GPIO(port_offset) & pins) && enabled) ? 1 : 0;
|
||||
|
||||
// Clear the interrupt status.
|
||||
if (status)
|
||||
_gpio_interrupt_clear(port, pins);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void gpio_interrupt_enable(u32 port, u32 pins, int enable)
|
||||
{
|
||||
u32 port_offset = GPIO_INT_ENB_OFFSET(port);
|
||||
|
||||
// Clear any possible stray interrupt.
|
||||
_gpio_interrupt_clear(port, pins);
|
||||
|
||||
if (enable)
|
||||
GPIO(port_offset) |= pins;
|
||||
else
|
||||
GPIO(port_offset) &= ~pins;
|
||||
|
||||
(void)GPIO(port_offset); // Commit the write.
|
||||
}
|
||||
|
||||
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta)
|
||||
{
|
||||
u32 port_offset = GPIO_INT_LVL_OFFSET(port);
|
||||
|
||||
u32 val = GPIO(port_offset);
|
||||
|
||||
if (high)
|
||||
val |= pins;
|
||||
else
|
||||
val &= ~pins;
|
||||
|
||||
if (edge)
|
||||
val |= pins << 8;
|
||||
else
|
||||
val &= ~(pins << 8);
|
||||
|
||||
if (delta)
|
||||
val |= pins << 16;
|
||||
else
|
||||
val &= ~(pins << 16);
|
||||
|
||||
GPIO(port_offset) = val;
|
||||
|
||||
(void)GPIO(port_offset); // Commit the write.
|
||||
|
||||
// Clear any possible stray interrupt.
|
||||
_gpio_interrupt_clear(port, pins);
|
||||
}
|
||||
|
||||
u32 gpio_get_bank_irq_id(u32 port)
|
||||
{
|
||||
u32 bank_idx = GPIO_BANK_IDX(port);
|
||||
|
||||
return gpio_bank_irq_ids[bank_idx];
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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,
|
||||
@@ -21,10 +22,23 @@
|
||||
|
||||
#define GPIO_MODE_SPIO 0
|
||||
#define GPIO_MODE_GPIO 1
|
||||
|
||||
#define GPIO_OUTPUT_DISABLE 0
|
||||
#define GPIO_OUTPUT_ENABLE 1
|
||||
|
||||
#define GPIO_IRQ_DISABLE 0
|
||||
#define GPIO_IRQ_ENABLE 1
|
||||
|
||||
#define GPIO_LOW 0
|
||||
#define GPIO_HIGH 1
|
||||
#define GPIO_FALLING 0
|
||||
#define GPIO_RISING 1
|
||||
|
||||
#define GPIO_LEVEL 0
|
||||
#define GPIO_EDGE 1
|
||||
|
||||
#define GPIO_CONFIGURED_EDGE 0
|
||||
#define GPIO_ANY_EDGE_CHANGE 1
|
||||
|
||||
/*! GPIO pins (0-7 for each port). */
|
||||
#define GPIO_PIN_0 (1 << 0)
|
||||
@@ -72,6 +86,10 @@
|
||||
void gpio_config(u32 port, u32 pins, int mode);
|
||||
void gpio_output_enable(u32 port, u32 pins, int enable);
|
||||
void gpio_write(u32 port, u32 pins, int high);
|
||||
int gpio_read(u32 port, u32 pins);
|
||||
int gpio_read(u32 port, u32 pins);
|
||||
int gpio_interrupt_status(u32 port, u32 pins);
|
||||
void gpio_interrupt_enable(u32 port, u32 pins, int enable);
|
||||
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta);
|
||||
u32 gpio_get_bank_irq_id(u32 port);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,10 +35,10 @@
|
||||
#include "../power/max7762x.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../sec/se_t210.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
extern sdmmc_t sd_sdmmc;
|
||||
extern boot_cfg_t b_cfg;
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
@@ -319,6 +319,9 @@ void config_hw()
|
||||
sdram_init();
|
||||
|
||||
bpmp_mmu_enable();
|
||||
|
||||
// Clear flags from PMC_SCRATCH0
|
||||
PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD;
|
||||
}
|
||||
|
||||
void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
|
||||
@@ -354,7 +357,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
|
||||
if (magic == 0xBAADF00D)
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) |= (1 << 22);
|
||||
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0);
|
||||
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
|
||||
clock_disable_cl_dvfs();
|
||||
|
||||
msleep(200);
|
||||
|
||||
@@ -38,21 +38,39 @@ static void _i2c_wait(vu32 *base)
|
||||
|
||||
static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size)
|
||||
{
|
||||
if (size > 4)
|
||||
if (size > 8)
|
||||
return 0;
|
||||
|
||||
u32 tmp = 0;
|
||||
memcpy(&tmp, buf, size);
|
||||
|
||||
vu32 *base = (vu32 *)i2c_addrs[idx];
|
||||
base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode).
|
||||
base[I2C_CMD_DATA1] = tmp; //Set value.
|
||||
base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode).
|
||||
|
||||
if (size > 4)
|
||||
{
|
||||
memcpy(&tmp, buf, 4);
|
||||
base[I2C_CMD_DATA1] = tmp; //Set value.
|
||||
tmp = 0;
|
||||
memcpy(&tmp, buf + 4, size - 4);
|
||||
base[I2C_CMD_DATA2] = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&tmp, buf, size);
|
||||
base[I2C_CMD_DATA1] = tmp; //Set value.
|
||||
}
|
||||
|
||||
base[I2C_CNFG] = ((size - 1) << 1) | 0x2800; //Set size and send mode.
|
||||
_i2c_wait(base); //Kick transaction.
|
||||
|
||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
|
||||
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
while (base[I2C_STATUS] & 0x100)
|
||||
;
|
||||
{
|
||||
if (get_tmr_ms() > timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (base[I2C_STATUS] << 28)
|
||||
return 0;
|
||||
@@ -71,8 +89,13 @@ static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x)
|
||||
_i2c_wait(base); // Kick transaction.
|
||||
|
||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
|
||||
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
while (base[I2C_STATUS] & 0x100)
|
||||
;
|
||||
{
|
||||
if (get_tmr_ms() > timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (base[I2C_STATUS] << 28)
|
||||
return 0;
|
||||
@@ -113,7 +136,7 @@ int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size)
|
||||
{
|
||||
u8 tmp[4];
|
||||
|
||||
if (size > 3)
|
||||
if (size > 7)
|
||||
return 0;
|
||||
|
||||
tmp[0] = y;
|
||||
|
||||
263
bootloader/soc/irq.c
Normal file
263
bootloader/soc/irq.c
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* BPMP-Lite IRQ driver for Tegra X1
|
||||
*
|
||||
* 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 "irq.h"
|
||||
#include "t210.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../mem/heap.h"
|
||||
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
|
||||
extern void irq_disable();
|
||||
extern void irq_enable_cpu_irq_exceptions();
|
||||
extern void irq_disable_cpu_irq_exceptions();
|
||||
|
||||
typedef struct _irq_ctxt_t
|
||||
{
|
||||
u32 irq;
|
||||
int (*handler)(u32 irq, void *data);
|
||||
void *data;
|
||||
u32 flags;
|
||||
} irq_ctxt_t;
|
||||
|
||||
bool irq_init_done = false;
|
||||
irq_ctxt_t irqs[IRQ_MAX_HANDLERS];
|
||||
|
||||
static void _irq_enable_source(u32 irq)
|
||||
{
|
||||
u32 ctrl_idx = irq >> 5;
|
||||
u32 bit = irq % 32;
|
||||
|
||||
// Set as normal IRQ.
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_COP_IEP_CLASS) &= ~(1 << bit);
|
||||
|
||||
// Enable IRQ source.
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_SET) = 1 << bit;
|
||||
}
|
||||
|
||||
static void _irq_disable_source(u32 irq)
|
||||
{
|
||||
u32 ctrl_idx = irq >> 5;
|
||||
u32 bit = irq % 32;
|
||||
|
||||
// Disable IRQ source.
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = 1 << bit;
|
||||
}
|
||||
|
||||
static void _irq_disable_and_ack_all()
|
||||
{
|
||||
// Disable and ack all IRQ sources.
|
||||
for (u32 ctrl_idx = 0; ctrl_idx < 6; ctrl_idx++)
|
||||
{
|
||||
u32 enabled_irqs = ICTLR(ctrl_idx, PRI_ICTLR_COP_IER);
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = enabled_irqs;
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = enabled_irqs;
|
||||
}
|
||||
}
|
||||
|
||||
static void _irq_ack_source(u32 irq)
|
||||
{
|
||||
u32 ctrl_idx = irq >> 5;
|
||||
u32 bit = irq % 32;
|
||||
|
||||
// Force stop the interrupt as it's serviced here.
|
||||
ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = 1 << bit;
|
||||
}
|
||||
|
||||
void irq_free(u32 irq)
|
||||
{
|
||||
for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
|
||||
{
|
||||
if (irqs[idx].irq == irq && irqs[idx].handler)
|
||||
{
|
||||
irqs[idx].irq = 0;
|
||||
irqs[idx].handler = NULL;
|
||||
irqs[idx].data = NULL;
|
||||
irqs[idx].flags = 0;
|
||||
|
||||
_irq_disable_source(irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _irq_free_all()
|
||||
{
|
||||
for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
|
||||
{
|
||||
if (irqs[idx].handler)
|
||||
{
|
||||
_irq_disable_source(irqs[idx].irq);
|
||||
|
||||
irqs[idx].irq = 0;
|
||||
irqs[idx].handler = NULL;
|
||||
irqs[idx].data = NULL;
|
||||
irqs[idx].flags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static irq_status_t _irq_handle_source(u32 irq)
|
||||
{
|
||||
int status = IRQ_NONE;
|
||||
|
||||
_irq_disable_source(irq);
|
||||
_irq_ack_source(irq);
|
||||
|
||||
u32 idx;
|
||||
for (idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
|
||||
{
|
||||
if (irqs[idx].irq == irq)
|
||||
{
|
||||
status = irqs[idx].handler(irqs[idx].irq, irqs[idx].data);
|
||||
|
||||
if (status == IRQ_HANDLED)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)
|
||||
irq_free(irq);
|
||||
else
|
||||
_irq_enable_source(irq);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void irq_handler()
|
||||
{
|
||||
// Get IRQ source.
|
||||
u32 irq = EXCP_VEC(EVP_COP_IRQ_STS) & 0xFF;
|
||||
|
||||
if (!irq_init_done)
|
||||
{
|
||||
_irq_ack_source(irq);
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF("IRQ: %d\n", irq);
|
||||
|
||||
int err = _irq_handle_source(irq);
|
||||
|
||||
//TODO: disable if unhandhled.
|
||||
if (err == IRQ_NONE)
|
||||
gfx_printf("Unhandled IRQ: %d\n", irq);
|
||||
}
|
||||
|
||||
static void _irq_init()
|
||||
{
|
||||
_irq_disable_and_ack_all();
|
||||
memset(irqs, 0, sizeof(irq_ctxt_t) * IRQ_MAX_HANDLERS);
|
||||
irq_init_done = true;
|
||||
}
|
||||
|
||||
void irq_end()
|
||||
{
|
||||
_irq_free_all();
|
||||
irq_disable_cpu_irq_exceptions();
|
||||
irq_init_done = false;
|
||||
}
|
||||
|
||||
void irq_wait_event(u32 irq)
|
||||
{
|
||||
irq_disable_cpu_irq_exceptions();
|
||||
|
||||
_irq_enable_source(irq);
|
||||
|
||||
// Halt BPMP and wait for the IRQ. No need to use WAIT_EVENT + LIC_IRQ when BPMP serves the IRQ.
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_STOP_UNTIL_IRQ;
|
||||
|
||||
_irq_disable_source(irq);
|
||||
_irq_ack_source(irq);
|
||||
|
||||
irq_enable_cpu_irq_exceptions();
|
||||
}
|
||||
|
||||
void irq_disable_wait_event()
|
||||
{
|
||||
irq_enable_cpu_irq_exceptions();
|
||||
}
|
||||
|
||||
irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t flags)
|
||||
{
|
||||
if (!irq_init_done)
|
||||
_irq_init();
|
||||
|
||||
for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++)
|
||||
{
|
||||
if (irqs[idx].handler == NULL ||
|
||||
(irqs[idx].irq == irq && irqs[idx].flags & IRQ_FLAG_REPLACEABLE))
|
||||
{
|
||||
DPRINTF("Registered handler, IRQ: %d, Slot: %d\n", irq, idx);
|
||||
DPRINTF("Handler: %08p, Flags: %x\n", (u32)handler, flags);
|
||||
|
||||
irqs[idx].irq = irq;
|
||||
irqs[idx].handler = handler;
|
||||
irqs[idx].data = data;
|
||||
irqs[idx].flags = flags;
|
||||
|
||||
_irq_enable_source(irq);
|
||||
|
||||
return IRQ_ENABLED;
|
||||
}
|
||||
else if (irqs[idx].irq == irq)
|
||||
return IRQ_ALREADY_REGISTERED;
|
||||
}
|
||||
|
||||
return IRQ_NO_SLOTS_AVAILABLE;
|
||||
}
|
||||
|
||||
void __attribute__ ((target("arm"))) fiq_setup()
|
||||
{
|
||||
/*
|
||||
asm volatile("mrs r12, cpsr\n\t"
|
||||
"bic r12, r12, #0x1F\n\t"
|
||||
"orr r12, r12, #0x11\n\t"
|
||||
"msr cpsr_c, r12\n\t");
|
||||
|
||||
register volatile char *text asm ("r8");
|
||||
register volatile char *uart_tx asm ("r9");
|
||||
register int len asm ("r10");
|
||||
|
||||
len = 5;
|
||||
uart_tx = (char *)0x70006040;
|
||||
memcpy((char *)text, "FIQ\r\n", len);
|
||||
*uart_tx = 0;
|
||||
|
||||
asm volatile("mrs r12, cpsr\n"
|
||||
"orr r12, r12, #0x1F\n"
|
||||
"msr cpsr_c, r12");
|
||||
*/
|
||||
}
|
||||
|
||||
void __attribute__ ((target("arm"), interrupt ("FIQ"))) fiq_handler()
|
||||
{
|
||||
/*
|
||||
register volatile char *text asm ("r8");
|
||||
register volatile char *uart_tx asm ("r9");
|
||||
register int len asm ("r10");
|
||||
|
||||
while (len)
|
||||
{
|
||||
*uart_tx = *text++;
|
||||
len--;
|
||||
}
|
||||
*/
|
||||
}
|
||||
222
bootloader/soc/irq.h
Normal file
222
bootloader/soc/irq.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* BPMP-Lite IRQ driver for Tegra X1
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef IRQ_H
|
||||
#define IRQ_H
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
#define IRQ_MAX_HANDLERS 16
|
||||
|
||||
/* Primary interrupt controller ids */
|
||||
#define IRQ_TMR1 0
|
||||
#define IRQ_TMR2 1
|
||||
#define IRQ_RTC 2
|
||||
#define IRQ_CEC 3
|
||||
#define IRQ_SHR_SEM_INBOX_FULL 4
|
||||
#define IRQ_SHR_SEM_INBOX_EMPTY 5
|
||||
#define IRQ_SHR_SEM_OUTBOX_FULL 6
|
||||
#define IRQ_SHR_SEM_OUTBOX_EMPTY 7
|
||||
#define IRQ_NVJPEG 8
|
||||
#define IRQ_NVDEC 9
|
||||
#define IRQ_QUAD_SPI 10
|
||||
#define IRQ_DPAUX_INT1 11
|
||||
#define IRQ_SATA_RX_STAT 13
|
||||
#define IRQ_SDMMC1 14
|
||||
#define IRQ_SDMMC2 15
|
||||
#define IRQ_VGPIO_INT 16
|
||||
#define IRQ_VII2C_INT 17
|
||||
#define IRQ_SDMMC3 19
|
||||
#define IRQ_USB 20
|
||||
#define IRQ_USB2 21
|
||||
#define IRQ_SATA_CTL 23
|
||||
#define IRQ_PMC_INT 24
|
||||
#define IRQ_FC_INT 25
|
||||
#define IRQ_APB_DMA_CPU 26
|
||||
#define IRQ_ARB_SEM_GNT_COP 28
|
||||
#define IRQ_ARB_SEM_GNT_CPU 29
|
||||
#define IRQ_SDMMC4 31
|
||||
|
||||
/* Secondary interrupt controller ids */
|
||||
#define IRQ_GPIO1 32
|
||||
#define IRQ_GPIO2 33
|
||||
#define IRQ_GPIO3 34
|
||||
#define IRQ_GPIO4 35
|
||||
#define IRQ_UARTA 36
|
||||
#define IRQ_UARTB 37
|
||||
#define IRQ_I2C 38
|
||||
#define IRQ_USB3_HOST_INT 39
|
||||
#define IRQ_USB3_HOST_SMI 40
|
||||
#define IRQ_TMR3 41
|
||||
#define IRQ_TMR4 42
|
||||
#define IRQ_USB3_HOST_PME 43
|
||||
#define IRQ_USB3_DEV_HOST 44
|
||||
#define IRQ_ACTMON 45
|
||||
#define IRQ_UARTC 46
|
||||
#define IRQ_THERMAL 48
|
||||
#define IRQ_XUSB_PADCTL 49
|
||||
#define IRQ_TSEC 50
|
||||
#define IRQ_EDP 51
|
||||
#define IRQ_I2C5 53
|
||||
#define IRQ_GPIO5 55
|
||||
#define IRQ_USB3_DEV_SMI 56
|
||||
#define IRQ_USB3_DEV_PME 57
|
||||
#define IRQ_SE 58
|
||||
#define IRQ_SPI1 59
|
||||
#define IRQ_APB_DMA_COP 60
|
||||
#define IRQ_CLDVFS 62
|
||||
#define IRQ_I2C6 63
|
||||
|
||||
/* Tertiary interrupt controller ids */
|
||||
#define IRQ_HOST1X_SYNCPT_COP 64
|
||||
#define IRQ_HOST1X_SYNCPT_CPU 65
|
||||
#define IRQ_HOST1X_GEN_COP 66
|
||||
#define IRQ_HOST1X_GEN_CPU 67
|
||||
#define IRQ_NVENC 68
|
||||
#define IRQ_VI 69
|
||||
#define IRQ_ISPB 70
|
||||
#define IRQ_ISP 71
|
||||
#define IRQ_VIC 72
|
||||
#define IRQ_DISPLAY 73
|
||||
#define IRQ_DISPLAYB 74
|
||||
#define IRQ_SOR1 75
|
||||
#define IRQ_SOR 76
|
||||
#define IRQ_MC 77
|
||||
#define IRQ_EMC 78
|
||||
#define IRQ_TSECB 80
|
||||
#define IRQ_HDA 81
|
||||
#define IRQ_SPI2 82
|
||||
#define IRQ_SPI3 83
|
||||
#define IRQ_I2C2 84
|
||||
#define IRQ_PMU_EXT 86
|
||||
#define IRQ_GPIO6 87
|
||||
#define IRQ_GPIO7 89
|
||||
#define IRQ_UARTD 90
|
||||
#define IRQ_I2C3 92
|
||||
#define IRQ_SPI4 93
|
||||
|
||||
/* Quaternary interrupt controller ids */
|
||||
#define IRQ_DTV 96
|
||||
#define IRQ_PCIE_INT 98
|
||||
#define IRQ_PCIE_MSI 99
|
||||
#define IRQ_AVP_CACHE 101
|
||||
#define IRQ_APE_INT1 102
|
||||
#define IRQ_APE_INT0 103
|
||||
#define IRQ_APB_DMA_CH0 104
|
||||
#define IRQ_APB_DMA_CH1 105
|
||||
#define IRQ_APB_DMA_CH2 106
|
||||
#define IRQ_APB_DMA_CH3 107
|
||||
#define IRQ_APB_DMA_CH4 108
|
||||
#define IRQ_APB_DMA_CH5 109
|
||||
#define IRQ_APB_DMA_CH6 110
|
||||
#define IRQ_APB_DMA_CH7 111
|
||||
#define IRQ_APB_DMA_CH8 112
|
||||
#define IRQ_APB_DMA_CH9 113
|
||||
#define IRQ_APB_DMA_CH10 114
|
||||
#define IRQ_APB_DMA_CH11 115
|
||||
#define IRQ_APB_DMA_CH12 116
|
||||
#define IRQ_APB_DMA_CH13 117
|
||||
#define IRQ_APB_DMA_CH14 118
|
||||
#define IRQ_APB_DMA_CH15 119
|
||||
#define IRQ_I2C4 120
|
||||
#define IRQ_TMR5 121
|
||||
#define IRQ_WDT_CPU 123
|
||||
#define IRQ_WDT_AVP 124
|
||||
#define IRQ_GPIO8 125
|
||||
#define IRQ_CAR 126
|
||||
|
||||
/* Quinary interrupt controller ids */
|
||||
#define IRQ_APB_DMA_CH16 128
|
||||
#define IRQ_APB_DMA_CH17 129
|
||||
#define IRQ_APB_DMA_CH18 130
|
||||
#define IRQ_APB_DMA_CH19 131
|
||||
#define IRQ_APB_DMA_CH20 132
|
||||
#define IRQ_APB_DMA_CH21 133
|
||||
#define IRQ_APB_DMA_CH22 134
|
||||
#define IRQ_APB_DMA_CH23 135
|
||||
#define IRQ_APB_DMA_CH24 136
|
||||
#define IRQ_APB_DMA_CH25 137
|
||||
#define IRQ_APB_DMA_CH26 138
|
||||
#define IRQ_APB_DMA_CH27 139
|
||||
#define IRQ_APB_DMA_CH28 140
|
||||
#define IRQ_APB_DMA_CH29 141
|
||||
#define IRQ_APB_DMA_CH30 142
|
||||
#define IRQ_APB_DMA_CH31 143
|
||||
#define IRQ_CPU0_PMU_INTR 144
|
||||
#define IRQ_CPU1_PMU_INTR 145
|
||||
#define IRQ_CPU2_PMU_INTR 146
|
||||
#define IRQ_CPU3_PMU_INTR 147
|
||||
#define IRQ_SDMMC1_SYS 148
|
||||
#define IRQ_SDMMC2_SYS 149
|
||||
#define IRQ_SDMMC3_SYS 150
|
||||
#define IRQ_SDMMC4_SYS 151
|
||||
#define IRQ_TMR6 152
|
||||
#define IRQ_TMR7 153
|
||||
#define IRQ_TMR8 154
|
||||
#define IRQ_TMR9 155
|
||||
#define IRQ_TMR0 156
|
||||
#define IRQ_GPU_STALL 157
|
||||
#define IRQ_GPU_NONSTALL 158
|
||||
#define IRQ_DPAUX 159
|
||||
|
||||
/* Senary interrupt controller ids */
|
||||
#define IRQ_MPCORE_AXIERRIRQ 160
|
||||
#define IRQ_MPCORE_INTERRIRQ 161
|
||||
#define IRQ_EVENT_GPIO_A 162
|
||||
#define IRQ_EVENT_GPIO_B 163
|
||||
#define IRQ_EVENT_GPIO_C 164
|
||||
#define IRQ_FLOW_RSM_CPU 168
|
||||
#define IRQ_FLOW_RSM_COP 169
|
||||
#define IRQ_TMR_SHARED 170
|
||||
#define IRQ_MPCORE_CTIIRQ0 171
|
||||
#define IRQ_MPCORE_CTIIRQ1 172
|
||||
#define IRQ_MPCORE_CTIIRQ2 173
|
||||
#define IRQ_MPCORE_CTIIRQ3 174
|
||||
#define IRQ_MSELECT_ERROR 175
|
||||
#define IRQ_TMR10 176
|
||||
#define IRQ_TMR11 177
|
||||
#define IRQ_TMR12 178
|
||||
#define IRQ_TMR13 179
|
||||
|
||||
typedef int (*irq_handler_t)(u32 irq, void *data);
|
||||
|
||||
typedef enum _irq_status_t
|
||||
{
|
||||
IRQ_NONE = 0,
|
||||
IRQ_HANDLED = 1,
|
||||
IRQ_ERROR = 2,
|
||||
|
||||
IRQ_ENABLED = 0,
|
||||
IRQ_NO_SLOTS_AVAILABLE = 1,
|
||||
IRQ_ALREADY_REGISTERED = 2
|
||||
} irq_status_t;
|
||||
|
||||
typedef enum _irq_flags_t
|
||||
{
|
||||
IRQ_FLAG_NONE = 0,
|
||||
IRQ_FLAG_ONE_OFF = (1 << 0),
|
||||
IRQ_FLAG_REPLACEABLE = (1 << 1)
|
||||
} irq_flags_t;
|
||||
|
||||
void irq_end();
|
||||
void irq_free(u32 irq);
|
||||
void irq_wait_event();
|
||||
void irq_disable_wait_event();
|
||||
irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t flags);
|
||||
|
||||
#endif
|
||||
@@ -62,6 +62,7 @@
|
||||
#define PINMUX_AUX_LCD_BL_PWM 0x1FC
|
||||
#define PINMUX_AUX_LCD_BL_EN 0x200
|
||||
#define PINMUX_AUX_LCD_RST 0x204
|
||||
#define PINMUX_AUX_LCD_GPIO1 0x208
|
||||
#define PINMUX_AUX_LCD_GPIO2 0x20C
|
||||
#define PINMUX_AUX_TOUCH_INT 0x220
|
||||
#define PINMUX_AUX_MOTION_INT 0x224
|
||||
|
||||
@@ -25,13 +25,23 @@
|
||||
#define APBDEV_PMC_PWRGATE_TOGGLE 0x30
|
||||
#define APBDEV_PMC_PWRGATE_STATUS 0x38
|
||||
#define APBDEV_PMC_NO_IOPOWER 0x44
|
||||
#define PMC_NO_IOPOWER_GPIO_IO_EN (1 << 21)
|
||||
#define PMC_NO_IOPOWER_AUDIO_HV (1 << 18)
|
||||
#define PMC_NO_IOPOWER_SDMMC1_IO_EN (1 << 12)
|
||||
#define APBDEV_PMC_SCRATCH0 0x50
|
||||
#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
|
||||
#define PMC_SCRATCH0_MODE_FASTBOOT (1 << 30)
|
||||
#define PMC_SCRATCH0_MODE_PAYLOAD (1 << 29)
|
||||
#define PMC_SCRATCH0_MODE_RCM (1 << 1)
|
||||
#define PMC_SCRATCH0_MODE_WARMBOOT (1 << 0)
|
||||
#define APBDEV_PMC_SCRATCH1 0x54
|
||||
#define APBDEV_PMC_SCRATCH20 0xA0
|
||||
#define APBDEV_PMC_PWR_DET_VAL 0xE4
|
||||
#define PMC_PWR_DET_GPIO_IO_EN (1 << 21)
|
||||
#define PMC_PWR_DET_AUDIO_HV (1 << 18)
|
||||
#define PMC_PWR_DET_SDMMC1_IO_EN (1 << 12)
|
||||
#define APBDEV_PMC_DDR_PWR 0xE8
|
||||
#define APBDEV_PMC_USB_AO 0xF0
|
||||
#define APBDEV_PMC_CRYPTO_OP 0xF4
|
||||
#define PMC_CRYPTO_OP_SE_ENABLE 0
|
||||
#define PMC_CRYPTO_OP_SE_DISABLE 1
|
||||
@@ -39,6 +49,8 @@
|
||||
#define APBDEV_PMC_SCRATCH40 0x13C
|
||||
#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4
|
||||
#define PMC_OSC_EDPD_OVER_OSC_CTRL_OVER 0x400000
|
||||
#define APBDEV_PMC_CLK_OUT_CNTRL 0x1A8
|
||||
#define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN (1 << 2)
|
||||
#define APBDEV_PMC_RST_STATUS 0x1B4
|
||||
#define APBDEV_PMC_IO_DPD_REQ 0x1B8
|
||||
#define APBDEV_PMC_IO_DPD2_REQ 0x1C0
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
#define VIC_BASE 0x54340000
|
||||
#define TSEC_BASE 0x54500000
|
||||
#define SOR1_BASE 0x54580000
|
||||
#define ICTLR_BASE 0x60004000
|
||||
#define TMR_BASE 0x60005000
|
||||
#define CLOCK_BASE 0x60006000
|
||||
#define FLOW_CTLR_BASE 0x60007000
|
||||
#define AHBDMA_BASE 0x60008000
|
||||
#define SYSREG_BASE 0x6000C000
|
||||
#define SB_BASE (SYSREG_BASE + 0x200)
|
||||
#define GPIO_BASE 0x6000D000
|
||||
@@ -44,6 +46,7 @@
|
||||
#define GPIO_8_BASE (GPIO_BASE + 0x700)
|
||||
#define EXCP_VEC_BASE 0x6000F000
|
||||
#define IPATCH_BASE 0x6001DC00
|
||||
#define APBDMA_BASE 0x60020000
|
||||
#define APB_MISC_BASE 0x70000000
|
||||
#define PINMUX_AUX_BASE 0x70003000
|
||||
#define UART_BASE 0x70006000
|
||||
@@ -56,10 +59,16 @@
|
||||
#define SE_BASE 0x70012000
|
||||
#define MC_BASE 0x70019000
|
||||
#define EMC_BASE 0x7001B000
|
||||
#define EMC0_BASE 0x7001E000
|
||||
#define EMC1_BASE 0x7001F000
|
||||
#define MIPI_CAL_BASE 0x700E3000
|
||||
#define CL_DVFS_BASE 0x70110000
|
||||
#define I2S_BASE 0x702D1000
|
||||
#define ADMA_BASE 0x702E2000
|
||||
#define TZRAM_BASE 0x7C010000
|
||||
#define USB_BASE 0x7D000000
|
||||
#define USB_OTG_BASE USB_BASE
|
||||
#define USB1_BASE 0x7D004000
|
||||
|
||||
#define _REG(base, off) *(vu32 *)((base) + (off))
|
||||
|
||||
@@ -70,10 +79,12 @@
|
||||
#define VIC(off) _REG(VIC_BASE, off)
|
||||
#define TSEC(off) _REG(TSEC_BASE, off)
|
||||
#define SOR1(off) _REG(SOR1_BASE, off)
|
||||
#define ICTLR(cidx, off) _REG(ICTLR_BASE + (0x100 * cidx), off)
|
||||
#define TMR(off) _REG(TMR_BASE, off)
|
||||
#define CLOCK(off) _REG(CLOCK_BASE, off)
|
||||
#define FLOW_CTLR(off) _REG(FLOW_CTLR_BASE, off)
|
||||
#define SYSREG(off) _REG(SYSREG_BASE, off)
|
||||
#define AHB_GIZMO(off) _REG(SYSREG_BASE, off)
|
||||
#define SB(off) _REG(SB_BASE, off)
|
||||
#define GPIO(off) _REG(GPIO_BASE, off)
|
||||
#define GPIO_1(off) _REG(GPIO_1_BASE, off)
|
||||
@@ -96,9 +107,14 @@
|
||||
#define SE(off) _REG(SE_BASE, off)
|
||||
#define MC(off) _REG(MC_BASE, off)
|
||||
#define EMC(off) _REG(EMC_BASE, off)
|
||||
#define EMC_CH0(off) _REG(EMC0_BASE, off)
|
||||
#define EMC_CH1(off) _REG(EMC1_BASE, off)
|
||||
#define MIPI_CAL(off) _REG(MIPI_CAL_BASE, off)
|
||||
#define I2S(off) _REG(I2S_BASE, off)
|
||||
#define CL_DVFS(off) _REG(CL_DVFS_BASE, off)
|
||||
#define I2S(off) _REG(I2S_BASE, off)
|
||||
#define ADMA(off) _REG(ADMA_BASE, off)
|
||||
#define USB(off) _REG(USB_BASE, off)
|
||||
#define USB1(off) _REG(USB1_BASE, off)
|
||||
#define TEST_REG(off) _REG(0x0, off)
|
||||
|
||||
/* HOST1X registers. */
|
||||
@@ -116,13 +132,40 @@
|
||||
#define EVP_COP_RSVD_VECTOR 0x214
|
||||
#define EVP_COP_IRQ_VECTOR 0x218
|
||||
#define EVP_COP_FIQ_VECTOR 0x21C
|
||||
#define EVP_COP_IRQ_STS 0x220
|
||||
|
||||
/*! Primary Interrupt Controller registers. */
|
||||
#define PRI_ICTLR_FIR 0x14
|
||||
#define PRI_ICTLR_FIR_SET 0x18
|
||||
#define PRI_ICTLR_FIR_CLR 0x1C
|
||||
#define PRI_ICTLR_CPU_IER 0x20
|
||||
#define PRI_ICTLR_CPU_IER_SET 0x24
|
||||
#define PRI_ICTLR_CPU_IER_CLR 0x28
|
||||
#define PRI_ICTLR_CPU_IEP_CLASS 0x2C
|
||||
#define PRI_ICTLR_COP_IER 0x30
|
||||
#define PRI_ICTLR_COP_IER_SET 0x34
|
||||
#define PRI_ICTLR_COP_IER_CLR 0x38
|
||||
#define PRI_ICTLR_COP_IEP_CLASS 0x3C
|
||||
|
||||
/*! AHB Gizmo registers. */
|
||||
#define AHB_ARBITRATION_PRIORITY_CTRL 0x8
|
||||
#define ARBITRATION_PRIORITY_CTRL_ENB_FAST_REARBITRATE (1 << 6)
|
||||
#define AHB_GIZMO_AHB_MEM 0x10
|
||||
#define AHB_MEM_ENB_FAST_REARBITRATE (1 << 2)
|
||||
#define AHB_GIZMO_USB 0x20
|
||||
#define AHB_GIZMO_USB_IMMEDIATE (1 << 18)
|
||||
#define AHB_AHB_MEM_PREFETCH_CFG1 0xF0
|
||||
#define MEM_PREFETCH_ENABLE (1 << 31)
|
||||
#define MEM_PREFETCH_AHB_MST_USB 6
|
||||
|
||||
/*! Misc registers. */
|
||||
#define APB_MISC_PP_STRAPPING_OPT_A 0x08
|
||||
#define APB_MISC_PP_PINMUX_GLOBAL 0x40
|
||||
#define APB_MISC_GP_HIDREV 0x804
|
||||
#define APB_MISC_GP_AUD_MCLK_CFGPADCTRL 0x8F4
|
||||
#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34
|
||||
#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98
|
||||
#define APB_MISC_GP_EMMC2_PAD_CFGPADCTRL 0xA9C
|
||||
#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL 0xAB4
|
||||
#define APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL 0xABC
|
||||
#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64
|
||||
@@ -170,9 +213,14 @@
|
||||
/*! TMR registers. */
|
||||
#define TIMERUS_CNTR_1US (0x10 + 0x0)
|
||||
#define TIMERUS_USEC_CFG (0x10 + 0x4)
|
||||
#define TIMER_TMR8_TMR_PTV 0x78
|
||||
#define TIMER_TMR9_TMR_PTV 0x80
|
||||
#define TIMER_EN (1 << 31)
|
||||
#define TIMER_PER_EN (1 << 30)
|
||||
#define TIMER_EN (1 << 31)
|
||||
#define TIMER_PER_EN (1 << 30)
|
||||
#define TIMER_TMR8_TMR_PCR 0x7C
|
||||
#define TIMER_TMR9_TMR_PCR 0x8C
|
||||
#define TIMER_INTR_CLR (1 << 30)
|
||||
|
||||
#define TIMER_WDT4_CONFIG (0x100 + 0x80)
|
||||
#define TIMER_SRC(TMR) (TMR & 0xF)
|
||||
#define TIMER_PER(PER) ((PER & 0xFF) << 4)
|
||||
@@ -210,13 +258,15 @@
|
||||
|
||||
/*! Flow controller registers. */
|
||||
#define FLOW_CTLR_HALT_COP_EVENTS 0x4
|
||||
#define HALT_COP_SEC (1 << 23)
|
||||
#define HALT_COP_MSEC (1 << 24)
|
||||
#define HALT_COP_USEC (1 << 25)
|
||||
#define HALT_COP_JTAG (1 << 28)
|
||||
#define HALT_COP_WAIT_EVENT (1 << 30)
|
||||
#define HALT_COP_WAIT_IRQ (1 << 31)
|
||||
#define HALT_COP_MAX_CNT 0xFF
|
||||
#define HALT_COP_GIC_IRQ (1 << 9)
|
||||
#define HALT_COP_LIC_IRQ (1 << 11)
|
||||
#define HALT_COP_SEC (1 << 23)
|
||||
#define HALT_COP_MSEC (1 << 24)
|
||||
#define HALT_COP_USEC (1 << 25)
|
||||
#define HALT_COP_JTAG (1 << 28)
|
||||
#define HALT_COP_WAIT_EVENT (1 << 30)
|
||||
#define HALT_COP_STOP_UNTIL_IRQ (1 << 31)
|
||||
#define HALT_COP_MAX_CNT 0xFF
|
||||
#define FLOW_CTLR_HALT_CPU0_EVENTS 0x0
|
||||
#define FLOW_CTLR_HALT_CPU1_EVENTS 0x14
|
||||
#define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C
|
||||
@@ -228,4 +278,9 @@
|
||||
#define FLOW_CTLR_RAM_REPAIR 0x40
|
||||
#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98
|
||||
|
||||
/*! USB controller registers. */
|
||||
#define USB1_UTMIP_BAT_CHRG_CFG0 0x830
|
||||
#define BAT_CHRG_CFG0_OP_SRC_EN (1 << 3)
|
||||
#define BAT_CHRG_CFG0_PWRDOWN_CHRG (1 << 0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2020 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,
|
||||
@@ -15,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "../soc/uart.h"
|
||||
#include "../soc/clock.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
@@ -28,12 +30,15 @@ void uart_init(u32 idx, u32 baud)
|
||||
// Make sure no data is being sent.
|
||||
uart_wait_idle(idx, UART_TX_IDLE);
|
||||
|
||||
// Set clock.
|
||||
bool clk_type = clock_uart_use_src_div(idx, baud);
|
||||
|
||||
// Misc settings.
|
||||
u32 rate = (8 * baud + 408000000) / (16 * baud);
|
||||
u32 div = clk_type ? ((8 * baud + 408000000) / (16 * baud)) : 1; // DIV_ROUND_CLOSEST.
|
||||
uart->UART_IER_DLAB = 0; // Disable interrupts.
|
||||
uart->UART_LCR = UART_LCR_DLAB | UART_LCR_WORD_LENGTH_8; // Enable DLAB & set 8n1 mode.
|
||||
uart->UART_THR_DLAB = (u8)rate; // Divisor latch LSB.
|
||||
uart->UART_IER_DLAB = (u8)(rate >> 8); // Divisor latch MSB.
|
||||
uart->UART_THR_DLAB = (u8)div; // Divisor latch LSB.
|
||||
uart->UART_IER_DLAB = (u8)(div >> 8); // Divisor latch MSB.
|
||||
uart->UART_LCR = UART_LCR_WORD_LENGTH_8; // Disable DLAB.
|
||||
(void)uart->UART_SPR;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2020 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,
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
.extern memset
|
||||
.type memset, %function
|
||||
|
||||
.extern ipl_main
|
||||
.type ipl_main, %function
|
||||
.extern _irq_setup
|
||||
.type _irq_setup, %function
|
||||
|
||||
.globl _start
|
||||
.type _start, %function
|
||||
@@ -67,7 +67,7 @@ _real_start:
|
||||
LDR R2, =__bss_end
|
||||
SUB R2, R2, R0
|
||||
BL memset
|
||||
BL ipl_main
|
||||
BL _irq_setup
|
||||
B .
|
||||
|
||||
.globl pivot_stack
|
||||
|
||||
@@ -24,21 +24,14 @@
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../utils/list.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
extern sdmmc_t sd_sdmmc;
|
||||
extern sdmmc_storage_t sd_storage;
|
||||
extern FATFS sd_fs;
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount();
|
||||
|
||||
void emummc_load_cfg()
|
||||
{
|
||||
sd_mount();
|
||||
emu_cfg.enabled = 0;
|
||||
emu_cfg.path = NULL;
|
||||
emu_cfg.nintendo_path = NULL;
|
||||
@@ -47,7 +40,8 @@ void emummc_load_cfg()
|
||||
emu_cfg.file_based_part_size = 0;
|
||||
emu_cfg.active_part = 0;
|
||||
emu_cfg.fs_ver = 0;
|
||||
emu_cfg.emummc_file_based_path = (char *)malloc(0x80);
|
||||
if (!emu_cfg.emummc_file_based_path)
|
||||
emu_cfg.emummc_file_based_path = (char *)malloc(0x80);
|
||||
|
||||
LIST_INIT(ini_sections);
|
||||
if (ini_parse(&ini_sections, "emuMMC/emummc.ini", false))
|
||||
@@ -78,6 +72,43 @@ void emummc_load_cfg()
|
||||
}
|
||||
}
|
||||
|
||||
void emummc_set_path(char *path)
|
||||
{
|
||||
FIL fp;
|
||||
bool found = false;
|
||||
|
||||
strcpy(emu_cfg.emummc_file_based_path, path);
|
||||
strcat(emu_cfg.emummc_file_based_path, "/raw_based");
|
||||
|
||||
if (!f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ))
|
||||
{
|
||||
if (!f_read(&fp, &emu_cfg.sector, 4, NULL))
|
||||
if (emu_cfg.sector)
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(emu_cfg.emummc_file_based_path, path);
|
||||
strcat(emu_cfg.emummc_file_based_path, "/file_based");
|
||||
|
||||
if (!f_stat(emu_cfg.emummc_file_based_path, NULL))
|
||||
{
|
||||
emu_cfg.sector = 0;
|
||||
emu_cfg.path = path;
|
||||
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
emu_cfg.enabled = 1;
|
||||
emu_cfg.id = 0;
|
||||
strcpy(emu_cfg.nintendo_path, path);
|
||||
strcpy(emu_cfg.nintendo_path, "/Nintendo");
|
||||
}
|
||||
}
|
||||
|
||||
static int emummc_raw_get_part_off(int part_idx)
|
||||
{
|
||||
switch (part_idx)
|
||||
@@ -95,7 +126,7 @@ static int emummc_raw_get_part_off(int part_idx)
|
||||
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
|
||||
{
|
||||
FILINFO fno;
|
||||
if (!sdmmc_storage_init_mmc(storage, sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(storage, sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
return 2;
|
||||
|
||||
if (h_cfg.emummc_force_disable)
|
||||
|
||||
@@ -50,6 +50,7 @@ typedef struct _emummc_cfg_t
|
||||
emummc_cfg_t emu_cfg;
|
||||
|
||||
void emummc_load_cfg();
|
||||
void emummc_set_path(char *path);
|
||||
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
||||
int emummc_storage_end(sdmmc_storage_t *storage);
|
||||
int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
|
||||
84
bootloader/storage/mbr_gpt.h
Normal file
84
bootloader/storage/mbr_gpt.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef MBR_GPT_H
|
||||
#define MBR_GPT_H
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
typedef struct _mbr_chs_t
|
||||
{
|
||||
u8 head;
|
||||
u8 sector;
|
||||
u8 cylinder;
|
||||
} __attribute__((packed)) mbr_chs_t;
|
||||
|
||||
typedef struct _mbr_part_t
|
||||
{
|
||||
u8 status;
|
||||
mbr_chs_t start_sct_chs;
|
||||
u8 type;
|
||||
mbr_chs_t end_sct_chs;
|
||||
u32 start_sct;
|
||||
u32 size_sct;
|
||||
} __attribute__((packed)) mbr_part_t;
|
||||
|
||||
typedef struct _mbr_t
|
||||
{
|
||||
u8 bootstrap[0x1B8];
|
||||
u32 signature;
|
||||
u16 copy_protected;
|
||||
mbr_part_t partitions[4];
|
||||
u16 boot_signature;
|
||||
} __attribute__((packed)) mbr_t;
|
||||
|
||||
typedef struct _gpt_entry_t
|
||||
{
|
||||
u8 type_guid[0x10];
|
||||
u8 part_guid[0x10];
|
||||
u64 lba_start;
|
||||
u64 lba_end;
|
||||
u64 attrs;
|
||||
u16 name[36];
|
||||
} gpt_entry_t;
|
||||
|
||||
typedef struct _gpt_header_t
|
||||
{
|
||||
u64 signature; // "EFI PART"
|
||||
u32 revision;
|
||||
u32 size;
|
||||
u32 crc32;
|
||||
u32 res1;
|
||||
u64 my_lba;
|
||||
u64 alt_lba;
|
||||
u64 first_use_lba;
|
||||
u64 last_use_lba;
|
||||
u8 disk_guid[0x10];
|
||||
u64 part_ent_lba;
|
||||
u32 num_part_ents;
|
||||
u32 part_ent_size;
|
||||
u32 part_ents_crc32;
|
||||
u8 res2[420]; // Used as first 3 partition entries backup for HOS.
|
||||
} gpt_header_t;
|
||||
|
||||
typedef struct _gpt_t
|
||||
{
|
||||
gpt_header_t header;
|
||||
gpt_entry_t entries[128];
|
||||
} gpt_t;
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mbr_gpt.h"
|
||||
#include "nx_emmc.h"
|
||||
#include "emummc.h"
|
||||
#include "../mem/heap.h"
|
||||
@@ -23,28 +24,31 @@
|
||||
|
||||
void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
|
||||
{
|
||||
u8 *buf = (u8 *)malloc(NX_GPT_NUM_BLOCKS * NX_EMMC_BLOCKSIZE);
|
||||
gpt_t *gpt_buf = (gpt_t *)calloc(NX_GPT_NUM_BLOCKS, NX_EMMC_BLOCKSIZE);
|
||||
|
||||
emummc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, buf);
|
||||
emummc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf);
|
||||
|
||||
gpt_header_t *hdr = (gpt_header_t *)buf;
|
||||
for (u32 i = 0; i < hdr->num_part_ents; i++)
|
||||
for (u32 i = 0; i < gpt_buf->header.num_part_ents; i++)
|
||||
{
|
||||
gpt_entry_t *ent = (gpt_entry_t *)(buf + (hdr->part_ent_lba - 1) * NX_EMMC_BLOCKSIZE + i * sizeof(gpt_entry_t));
|
||||
emmc_part_t *part = (emmc_part_t *)calloc(sizeof(emmc_part_t), 1);
|
||||
part->lba_start = ent->lba_start;
|
||||
part->lba_end = ent->lba_end;
|
||||
part->attrs = ent->attrs;
|
||||
|
||||
if (gpt_buf->entries[i].lba_start < gpt_buf->header.first_use_lba)
|
||||
continue;
|
||||
|
||||
part->index = i;
|
||||
part->lba_start = gpt_buf->entries[i].lba_start;
|
||||
part->lba_end = gpt_buf->entries[i].lba_end;
|
||||
part->attrs = gpt_buf->entries[i].attrs;
|
||||
|
||||
// ASCII conversion. Copy only the LSByte of the UTF-16LE name.
|
||||
for (u32 i = 0; i < 36; i++)
|
||||
part->name[i] = ent->name[i];
|
||||
part->name[36] = 0;
|
||||
for (u32 j = 0; j < 36; j++)
|
||||
part->name[j] = gpt_buf->entries[i].name[j];
|
||||
part->name[35] = 0;
|
||||
|
||||
list_append(gpt, &part->link);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
free(gpt_buf);
|
||||
}
|
||||
|
||||
void nx_emmc_gpt_free(link_t *gpt)
|
||||
|
||||
@@ -17,38 +17,9 @@
|
||||
#ifndef _NX_EMMC_H_
|
||||
#define _NX_EMMC_H_
|
||||
|
||||
#include "sdmmc.h"
|
||||
#include "../utils/types.h"
|
||||
#include "../utils/list.h"
|
||||
#include "sdmmc.h"
|
||||
|
||||
typedef struct _gpt_entry_t
|
||||
{
|
||||
u8 type_guid[0x10];
|
||||
u8 part_guid[0x10];
|
||||
u64 lba_start;
|
||||
u64 lba_end;
|
||||
u64 attrs;
|
||||
u16 name[36];
|
||||
} gpt_entry_t;
|
||||
|
||||
typedef struct _gpt_header_t
|
||||
{
|
||||
u64 signature;
|
||||
u32 revision;
|
||||
u32 size;
|
||||
u32 crc32;
|
||||
u32 res1;
|
||||
u64 my_lba;
|
||||
u64 alt_lba;
|
||||
u64 first_use_lba;
|
||||
u64 last_use_lba;
|
||||
u8 disk_guid[0x10];
|
||||
u64 part_ent_lba;
|
||||
u32 num_part_ents;
|
||||
u32 part_ent_size;
|
||||
u32 part_ents_crc32;
|
||||
u8 res2[420];
|
||||
} gpt_header_t;
|
||||
|
||||
#define NX_GPT_FIRST_LBA 1
|
||||
#define NX_GPT_NUM_BLOCKS 33
|
||||
@@ -56,6 +27,7 @@ typedef struct _gpt_header_t
|
||||
|
||||
typedef struct _emmc_part_t
|
||||
{
|
||||
u32 index;
|
||||
u32 lba_start;
|
||||
u32 lba_end;
|
||||
u64 attrs;
|
||||
|
||||
179
bootloader/storage/nx_sd.c
Normal file
179
bootloader/storage/nx_sd.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-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 "nx_sd.h"
|
||||
#include "sdmmc.h"
|
||||
#include "sdmmc_driver.h"
|
||||
#include "../gfx/gfx.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
|
||||
static bool sd_mounted = false;
|
||||
static u32 sd_mode = SD_UHS_SDR82;
|
||||
|
||||
u32 sd_get_mode()
|
||||
{
|
||||
return sd_mode;
|
||||
}
|
||||
|
||||
int sd_init_retry(bool power_cycle)
|
||||
{
|
||||
u32 bus_width = SDMMC_BUS_WIDTH_4;
|
||||
u32 type = SDHCI_TIMING_UHS_SDR82;
|
||||
|
||||
// Power cycle SD card.
|
||||
if (power_cycle)
|
||||
{
|
||||
sd_mode--;
|
||||
sdmmc_storage_end(&sd_storage);
|
||||
}
|
||||
|
||||
// Get init parameters.
|
||||
switch (sd_mode)
|
||||
{
|
||||
case SD_INIT_FAIL: // Reset to max.
|
||||
return 0;
|
||||
case SD_1BIT_HS25:
|
||||
bus_width = SDMMC_BUS_WIDTH_1;
|
||||
type = SDHCI_TIMING_SD_HS25;
|
||||
break;
|
||||
case SD_4BIT_HS25:
|
||||
type = SDHCI_TIMING_SD_HS25;
|
||||
break;
|
||||
case SD_UHS_SDR82:
|
||||
type = SDHCI_TIMING_UHS_SDR82;
|
||||
break;
|
||||
default:
|
||||
sd_mode = SD_UHS_SDR82;
|
||||
}
|
||||
|
||||
return sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type);
|
||||
}
|
||||
|
||||
bool sd_initialize(bool power_cycle)
|
||||
{
|
||||
if (power_cycle)
|
||||
sdmmc_storage_end(&sd_storage);
|
||||
|
||||
int res = !sd_init_retry(false);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!res)
|
||||
return true;
|
||||
else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted.
|
||||
{
|
||||
sd_mode = SD_UHS_SDR82;
|
||||
break;
|
||||
}
|
||||
else if (sd_mode == SD_INIT_FAIL)
|
||||
break;
|
||||
else
|
||||
res = !sd_init_retry(true);
|
||||
}
|
||||
|
||||
sdmmc_storage_end(&sd_storage);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sd_mount()
|
||||
{
|
||||
if (sd_mounted)
|
||||
return true;
|
||||
|
||||
int res = !sd_initialize(false);
|
||||
|
||||
if (res)
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
EPRINTF("Failed to init SD card.");
|
||||
if (!sdmmc_get_sd_inserted())
|
||||
EPRINTF("Make sure that it is inserted.");
|
||||
else
|
||||
EPRINTF("SD Card Reader is not properly seated!");
|
||||
}
|
||||
else
|
||||
{
|
||||
res = f_mount(&sd_fs, "", 1);
|
||||
if (res == FR_OK)
|
||||
{
|
||||
sd_mounted = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
EPRINTFARGS("Failed to mount SD card (FatFS Error %d).\nMake sure that a FAT partition exists..", res);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void sd_unmount()
|
||||
{
|
||||
sd_mode = SD_UHS_SDR82;
|
||||
if (sd_mounted)
|
||||
{
|
||||
f_mount(NULL, "", 1);
|
||||
sdmmc_storage_end(&sd_storage);
|
||||
sd_mounted = false;
|
||||
}
|
||||
}
|
||||
|
||||
void *sd_file_read(const char *path, u32 *fsize)
|
||||
{
|
||||
FIL fp;
|
||||
if (f_open(&fp, path, FA_READ) != FR_OK)
|
||||
return NULL;
|
||||
|
||||
u32 size = f_size(&fp);
|
||||
if (fsize)
|
||||
*fsize = size;
|
||||
|
||||
void *buf = malloc(size);
|
||||
|
||||
if (f_read(&fp, buf, size, NULL) != FR_OK)
|
||||
{
|
||||
free(buf);
|
||||
f_close(&fp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f_close(&fp);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int sd_save_to_file(void *buf, u32 size, const char *filename)
|
||||
{
|
||||
FIL fp;
|
||||
u32 res = 0;
|
||||
res = f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (res)
|
||||
{
|
||||
EPRINTFARGS("Error (%d) creating file\n%s.\n", res, filename);
|
||||
return res;
|
||||
}
|
||||
|
||||
f_write(&fp, buf, size, NULL);
|
||||
f_close(&fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
45
bootloader/storage/nx_sd.h
Normal file
45
bootloader/storage/nx_sd.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-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/>.
|
||||
*/
|
||||
|
||||
#ifndef NX_SD_H
|
||||
#define NX_SD_H
|
||||
|
||||
#include "sdmmc.h"
|
||||
#include "sdmmc_driver.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
|
||||
enum
|
||||
{
|
||||
SD_INIT_FAIL = 0,
|
||||
SD_1BIT_HS25 = 1,
|
||||
SD_4BIT_HS25 = 2,
|
||||
SD_UHS_SDR82 = 3,
|
||||
};
|
||||
|
||||
sdmmc_t sd_sdmmc;
|
||||
sdmmc_storage_t sd_storage;
|
||||
FATFS sd_fs;
|
||||
|
||||
u32 sd_get_mode();
|
||||
int sd_init_retry(bool power_cycle);
|
||||
bool sd_initialize(bool power_cycle);
|
||||
bool sd_mount();
|
||||
void sd_unmount();
|
||||
void *sd_file_read(const char *path, u32 *fsize);
|
||||
int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
|
||||
#endif
|
||||
@@ -106,6 +106,11 @@
|
||||
#define SD_SET_CURRENT_LIMIT_600 2
|
||||
#define SD_SET_CURRENT_LIMIT_800 3
|
||||
|
||||
#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200)
|
||||
#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400)
|
||||
#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600)
|
||||
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
|
||||
|
||||
/*
|
||||
* SD_SWITCH mode
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <string.h>
|
||||
#include "sdmmc.h"
|
||||
#include "mmc.h"
|
||||
#include "nx_sd.h"
|
||||
#include "sd.h"
|
||||
#include "../../common/memory_map.h"
|
||||
#include "../gfx/gfx.h"
|
||||
@@ -135,10 +136,12 @@ static int _sdmmc_storage_check_status(sdmmc_storage_t *storage)
|
||||
|
||||
static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
||||
{
|
||||
u32 tmp = 0;
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_req_t reqbuf;
|
||||
|
||||
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
|
||||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.num_sectors = num_sectors;
|
||||
reqbuf.blksize = 512;
|
||||
@@ -148,7 +151,6 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
|
||||
{
|
||||
u32 tmp = 0;
|
||||
sdmmc_stop_transmission(storage->sdmmc, &tmp);
|
||||
_sdmmc_storage_get_status(storage, &tmp, 0);
|
||||
|
||||
@@ -171,25 +173,42 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
|
||||
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
||||
{
|
||||
u8 *bbuf = (u8 *)buf;
|
||||
|
||||
bool first_reinit = false;
|
||||
while (num_sectors)
|
||||
{
|
||||
u32 blkcnt = 0;
|
||||
//Retry 9 times on error.
|
||||
u32 retries = 10;
|
||||
// Retry 5 times if failed.
|
||||
u32 retries = 5;
|
||||
do
|
||||
{
|
||||
reinit_try:
|
||||
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write))
|
||||
goto out;
|
||||
else
|
||||
retries--;
|
||||
|
||||
msleep(100);
|
||||
msleep(50);
|
||||
} while (retries);
|
||||
|
||||
// Disk IO failure! Reinit SD Card to a lower speed.
|
||||
if (storage->sdmmc->id == SDMMC_1)
|
||||
{
|
||||
int res;
|
||||
if (!first_reinit)
|
||||
res = sd_initialize(true);
|
||||
else
|
||||
res = sd_init_retry(true);
|
||||
|
||||
retries = 3;
|
||||
first_reinit = true;
|
||||
|
||||
if (res)
|
||||
goto reinit_try;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:;
|
||||
out:
|
||||
DPRINTF("readwrite: %08X\n", blkcnt);
|
||||
sector += blkcnt;
|
||||
num_sectors -= blkcnt;
|
||||
@@ -201,12 +220,34 @@ DPRINTF("readwrite: %08X\n", blkcnt);
|
||||
|
||||
int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf)
|
||||
{
|
||||
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 0);
|
||||
// Ensure that buffer resides in DRAM and it's DMA aligned.
|
||||
if (((u32)buf >= DRAM_START) && !((u32)buf % 8))
|
||||
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 0);
|
||||
|
||||
if (num_sectors > (SDMMC_UP_BUF_SZ / 512))
|
||||
return 0;
|
||||
|
||||
u8 *tmp_buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
if (_sdmmc_storage_readwrite(storage, sector, num_sectors, tmp_buf, 0))
|
||||
{
|
||||
memcpy(buf, tmp_buf, 512 * num_sectors);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf)
|
||||
{
|
||||
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 1);
|
||||
// Ensure that buffer resides in DRAM and it's DMA aligned.
|
||||
if (((u32)buf >= DRAM_START) && !((u32)buf % 8))
|
||||
return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 1);
|
||||
|
||||
if (num_sectors > (SDMMC_UP_BUF_SZ / 512))
|
||||
return 0;
|
||||
|
||||
u8 *tmp_buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
memcpy(tmp_buf, buf, 512 * num_sectors);
|
||||
return _sdmmc_storage_readwrite(storage, sector, num_sectors, tmp_buf, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -401,7 +442,7 @@ static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, int check)
|
||||
if (check && !_sdmmc_storage_check_status(storage))
|
||||
return 0;
|
||||
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 2))
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS52))
|
||||
return 0;
|
||||
|
||||
DPRINTF("[MMC] switched to HS\n");
|
||||
@@ -418,10 +459,10 @@ static int _mmc_storage_enable_HS200(sdmmc_storage_t *storage)
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200)))
|
||||
return 0;
|
||||
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 3))
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS200))
|
||||
return 0;
|
||||
|
||||
if (!sdmmc_config_tuning(storage->sdmmc, 3, MMC_SEND_TUNING_BLOCK_HS200))
|
||||
if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS200, MMC_SEND_TUNING_BLOCK_HS200))
|
||||
return 0;
|
||||
|
||||
DPRINTF("[MMC] switched to HS200\n");
|
||||
@@ -435,7 +476,7 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage)
|
||||
if (!_mmc_storage_enable_HS200(storage))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_venclkctl(storage->sdmmc);
|
||||
sdmmc_set_tap_value(storage->sdmmc);
|
||||
|
||||
if (!_mmc_storage_enable_HS(storage, 0))
|
||||
return 0;
|
||||
@@ -446,7 +487,7 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage)
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400)))
|
||||
return 0;
|
||||
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 4))
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS400))
|
||||
return 0;
|
||||
|
||||
DPRINTF("[MMC] switched to HS400\n");
|
||||
@@ -457,22 +498,20 @@ DPRINTF("[MMC] switched to HS400\n");
|
||||
|
||||
static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type, u32 type)
|
||||
{
|
||||
//TODO: this should be a config item.
|
||||
// --v
|
||||
if (!1 || sdmmc_get_voltage(storage->sdmmc) != SDMMC_POWER_1_8)
|
||||
if (sdmmc_get_io_power(storage->sdmmc) != SDMMC_POWER_1_8)
|
||||
goto out;
|
||||
|
||||
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 &&
|
||||
card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && type == 4)
|
||||
card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && type == SDHCI_TIMING_MMC_HS400)
|
||||
return _mmc_storage_enable_HS400(storage);
|
||||
|
||||
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 ||
|
||||
(sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_4
|
||||
&& card_type & EXT_CSD_CARD_TYPE_HS200_1_8V
|
||||
&& (type == 4 || type == 3)))
|
||||
&& (type == SDHCI_TIMING_MMC_HS400 || type == SDHCI_TIMING_MMC_HS200)))
|
||||
return _mmc_storage_enable_HS200(storage);
|
||||
|
||||
out:;
|
||||
out:
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS_52)
|
||||
return _mmc_storage_enable_HS(storage, 1);
|
||||
|
||||
@@ -487,13 +526,13 @@ static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
|
||||
return _sdmmc_storage_check_status(storage);
|
||||
}
|
||||
|
||||
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, 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));
|
||||
storage->sdmmc = sdmmc;
|
||||
storage->rca = 2; //TODO: this could be a config item.
|
||||
|
||||
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, 0, 0))
|
||||
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_AUTO_CAL_DISABLE))
|
||||
return 0;
|
||||
DPRINTF("[MMC] after init\n");
|
||||
|
||||
@@ -520,7 +559,7 @@ DPRINTF("[MMC] set relative addr\n");
|
||||
DPRINTF("[MMC] got csd\n");
|
||||
_mmc_storage_parse_csd(storage);
|
||||
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 1))
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_LS26))
|
||||
return 0;
|
||||
DPRINTF("[MMC] after setup clock\n");
|
||||
|
||||
@@ -544,35 +583,27 @@ DPRINTF("[MMC] set blocklen to 512\n");
|
||||
return 0;
|
||||
DPRINTF("[MMC] switched buswidth\n");
|
||||
|
||||
u8 *ext_csd = (u8 *)malloc(512);
|
||||
if (!_mmc_storage_get_ext_csd(storage, ext_csd))
|
||||
{
|
||||
free(ext_csd);
|
||||
if (!_mmc_storage_get_ext_csd(storage, (u8 *)SDMMC_UPPER_BUFFER))
|
||||
return 0;
|
||||
}
|
||||
free(ext_csd);
|
||||
DPRINTF("[MMC] got ext_csd\n");
|
||||
|
||||
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
|
||||
//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().
|
||||
Additionally this works only when we put the device in idle mode which we don't after enabling it. */
|
||||
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2) && 0)
|
||||
if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2))
|
||||
{
|
||||
_mmc_storage_enable_bkops(storage);
|
||||
DPRINTF("[MMC] BKOPS enabled\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF("[MMC] BKOPS disabled\n");
|
||||
}
|
||||
|
||||
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
|
||||
return 0;
|
||||
DPRINTF("[MMC] succesfully switched to HS mode\n");
|
||||
|
||||
sdmmc_sd_clock_ctrl(storage->sdmmc, 1);
|
||||
sdmmc_card_clock_ctrl(storage->sdmmc, SDMMC_AUTO_CAL_ENABLE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -656,6 +687,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
|
||||
if (cond & SD_OCR_CCS)
|
||||
storage->has_sector_access = 1;
|
||||
|
||||
// Check if card supports 1.8V signaling.
|
||||
if (cond & SD_ROCR_S18A && supports_low_voltage)
|
||||
{
|
||||
//The low voltage regulator configuration is valid for SDMMC1 only.
|
||||
@@ -804,34 +836,37 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
|
||||
return _sdmmc_storage_check_result(tmp);
|
||||
}
|
||||
|
||||
void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u8 *buf)
|
||||
void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf)
|
||||
{
|
||||
u32 pwr = SD_SET_CURRENT_LIMIT_800;
|
||||
u32 pwr = SD_SET_CURRENT_LIMIT_200;
|
||||
|
||||
if (current_limit & SD_MAX_CURRENT_800)
|
||||
pwr = SD_SET_CURRENT_LIMIT_800;
|
||||
else if (current_limit & SD_MAX_CURRENT_600)
|
||||
pwr = SD_SET_CURRENT_LIMIT_600;
|
||||
else if (current_limit & SD_MAX_CURRENT_400)
|
||||
pwr = SD_SET_CURRENT_LIMIT_400;
|
||||
|
||||
_sd_storage_switch(storage, buf, SD_SWITCH_SET, 3, pwr);
|
||||
|
||||
while (pwr > 0)
|
||||
if (((buf[15] >> 4) & 0x0F) == pwr)
|
||||
{
|
||||
pwr--;
|
||||
_sd_storage_switch(storage, buf, SD_SWITCH_SET, 3, pwr);
|
||||
if (((buf[15] >> 4) & 0x0F) == pwr)
|
||||
switch (pwr)
|
||||
{
|
||||
case SD_SET_CURRENT_LIMIT_800:
|
||||
DPRINTF("[SD] power limit raised to 800mA\n");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pwr)
|
||||
{
|
||||
case SD_SET_CURRENT_LIMIT_800:
|
||||
DPRINTF("[SD] power limit raised to 800mA\n");
|
||||
break;
|
||||
case SD_SET_CURRENT_LIMIT_600:
|
||||
case SD_SET_CURRENT_LIMIT_600:
|
||||
DPRINTF("[SD] power limit raised to 600mA\n");
|
||||
break;
|
||||
case SD_SET_CURRENT_LIMIT_400:
|
||||
DPRINTF("[SD] power limit raised to 800mA\n");
|
||||
break;
|
||||
default:
|
||||
case SD_SET_CURRENT_LIMIT_200:
|
||||
break;
|
||||
case SD_SET_CURRENT_LIMIT_400:
|
||||
DPRINTF("[SD] power limit raised to 400mA\n");
|
||||
break;
|
||||
default:
|
||||
case SD_SET_CURRENT_LIMIT_200:
|
||||
DPRINTF("[SD] power limit defaulted to 200mA\n");
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -839,30 +874,33 @@ int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf)
|
||||
{
|
||||
if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type))
|
||||
return 0;
|
||||
DPRINTF("[SD] SD supports switch to (U)HS check\n");
|
||||
DPRINTF("[SD] supports switch to (U)HS mode\n");
|
||||
|
||||
u32 type_out = buf[16] & 0xF;
|
||||
if (type_out != hs_type)
|
||||
return 0;
|
||||
DPRINTF("[SD] SD supports selected (U)HS mode\n");
|
||||
DPRINTF("[SD] supports selected (U)HS mode\n");
|
||||
|
||||
if ((((u16)buf[0] << 8) | buf[1]) < 0x320)
|
||||
u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1];
|
||||
DPRINTF("[SD] total max current: %d\n", total_pwr_consumption);
|
||||
|
||||
if (total_pwr_consumption <= 800)
|
||||
{
|
||||
if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, 0, hs_type))
|
||||
return 0;
|
||||
|
||||
if (type_out != (buf[16] & 0xF))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
DPRINTF("[SD] card max current over limit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u8 *buf)
|
||||
{
|
||||
// Try to raise the current limit to let the card perform better.
|
||||
_sd_storage_set_current_limit(storage, buf);
|
||||
|
||||
if (sdmmc_get_bus_width(storage->sdmmc) != SDMMC_BUS_WIDTH_4)
|
||||
return 0;
|
||||
|
||||
@@ -870,32 +908,55 @@ int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u8 *buf)
|
||||
return 0;
|
||||
//gfx_hexdump(0, (u8 *)buf, 64);
|
||||
|
||||
u8 access_mode = buf[13];
|
||||
u16 current_limit = buf[7] | buf[6] << 8;
|
||||
|
||||
// Try to raise the current limit to let the card perform better.
|
||||
_sd_storage_set_current_limit(storage, current_limit, buf);
|
||||
|
||||
u32 hs_type = 0;
|
||||
switch (type)
|
||||
{
|
||||
case 11: // SDR104.
|
||||
case SDHCI_TIMING_UHS_SDR104:
|
||||
case SDHCI_TIMING_UHS_SDR82:
|
||||
// Fall through if not supported.
|
||||
if (buf[13] & SD_MODE_UHS_SDR104)
|
||||
if (access_mode & SD_MODE_UHS_SDR104)
|
||||
{
|
||||
type = 11;
|
||||
hs_type = UHS_SDR104_BUS_SPEED;
|
||||
DPRINTF("[SD] bus speed set to SDR104\n");
|
||||
storage->csd.busspeed = 104;
|
||||
switch (type)
|
||||
{
|
||||
case SDHCI_TIMING_UHS_SDR104:
|
||||
storage->csd.busspeed = 104;
|
||||
break;
|
||||
case SDHCI_TIMING_UHS_SDR82:
|
||||
storage->csd.busspeed = 82;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 10: // SDR50.
|
||||
if (buf[13] & SD_MODE_UHS_SDR50)
|
||||
case SDHCI_TIMING_UHS_SDR50:
|
||||
if (access_mode & SD_MODE_UHS_SDR50)
|
||||
{
|
||||
type = 10;
|
||||
type = SDHCI_TIMING_UHS_SDR50;
|
||||
hs_type = UHS_SDR50_BUS_SPEED;
|
||||
DPRINTF("[SD] bus speed set to SDR50\n");
|
||||
storage->csd.busspeed = 50;
|
||||
break;
|
||||
}
|
||||
case 8: // SDR12.
|
||||
if (!(buf[13] & SD_MODE_UHS_SDR12))
|
||||
case SDHCI_TIMING_UHS_SDR25:
|
||||
if (access_mode & SD_MODE_UHS_SDR25)
|
||||
{
|
||||
type = SDHCI_TIMING_UHS_SDR25;
|
||||
hs_type = UHS_SDR50_BUS_SPEED;
|
||||
DPRINTF("[SD] bus speed set to SDR25\n");
|
||||
storage->csd.busspeed = 25;
|
||||
break;
|
||||
}
|
||||
case SDHCI_TIMING_UHS_SDR12:
|
||||
if (!(access_mode & SD_MODE_UHS_SDR12))
|
||||
return 0;
|
||||
type = 8;
|
||||
type = SDHCI_TIMING_UHS_SDR12;
|
||||
hs_type = UHS_SDR12_BUS_SPEED;
|
||||
DPRINTF("[SD] bus speed set to SDR12\n");
|
||||
storage->csd.busspeed = 12;
|
||||
@@ -907,11 +968,11 @@ DPRINTF("[SD] bus speed set to SDR12\n");
|
||||
|
||||
if (!_sd_storage_enable_highspeed(storage, hs_type, buf))
|
||||
return 0;
|
||||
DPRINTF("[SD] SD card accepted UHS\n");
|
||||
DPRINTF("[SD] card accepted UHS\n");
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, type))
|
||||
return 0;
|
||||
DPRINTF("[SD] setup clock\n");
|
||||
if (!sdmmc_config_tuning(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK))
|
||||
if (!sdmmc_tuning_execute(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK))
|
||||
return 0;
|
||||
DPRINTF("[SD] config tuning\n");
|
||||
return _sdmmc_storage_check_status(storage);
|
||||
@@ -922,16 +983,23 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
||||
if (!_sd_storage_switch_get(storage, buf))
|
||||
return 0;
|
||||
//gfx_hexdump(0, (u8 *)buf, 64);
|
||||
if (!(buf[13] & SD_MODE_HIGH_SPEED))
|
||||
|
||||
u8 access_mode = buf[13];
|
||||
u16 current_limit = buf[7] | buf[6] << 8;
|
||||
|
||||
// Try to raise the current limit to let the card perform better.
|
||||
_sd_storage_set_current_limit(storage, current_limit, buf);
|
||||
|
||||
if (!(access_mode & SD_MODE_HIGH_SPEED))
|
||||
return 1;
|
||||
|
||||
if (!_sd_storage_enable_highspeed(storage, 1, buf))
|
||||
if (!_sd_storage_enable_highspeed(storage, HIGH_SPEED_BUS_SPEED, buf))
|
||||
return 0;
|
||||
|
||||
if (!_sdmmc_storage_check_status(storage))
|
||||
return 0;
|
||||
|
||||
return sdmmc_setup_clock(storage->sdmmc, 7);
|
||||
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
|
||||
}
|
||||
|
||||
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
@@ -1055,6 +1123,23 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
}
|
||||
}
|
||||
|
||||
static bool _sdmmc_storage_supports_low_voltage(u32 bus_width, u32 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SDHCI_TIMING_UHS_SDR12:
|
||||
case SDHCI_TIMING_UHS_SDR25:
|
||||
case SDHCI_TIMING_UHS_SDR50:
|
||||
case SDHCI_TIMING_UHS_SDR104:
|
||||
case SDHCI_TIMING_UHS_SDR82:
|
||||
case SDHCI_TIMING_UHS_DDR50:
|
||||
if (bus_width == SDMMC_BUS_WIDTH_4)
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void sdmmc_storage_init_wait_sd()
|
||||
{
|
||||
u32 sd_poweroff_time = (u32)get_tmr_ms() - sd_power_cycle_time_start;
|
||||
@@ -1062,7 +1147,7 @@ void sdmmc_storage_init_wait_sd()
|
||||
msleep(100 - sd_poweroff_time);
|
||||
}
|
||||
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, 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;
|
||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
@@ -1073,7 +1158,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
memset(storage, 0, sizeof(sdmmc_storage_t));
|
||||
storage->sdmmc = sdmmc;
|
||||
|
||||
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0))
|
||||
if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, SDMMC_AUTO_CAL_DISABLE))
|
||||
return 0;
|
||||
DPRINTF("[SD] after init\n");
|
||||
|
||||
@@ -1088,7 +1173,9 @@ DPRINTF("[SD] went to idle state\n");
|
||||
return 0;
|
||||
DPRINTF("[SD] after send if cond\n");
|
||||
|
||||
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_width == SDMMC_BUS_WIDTH_4 && type == 11))
|
||||
bool supports_low_voltage = _sdmmc_storage_supports_low_voltage(bus_width, type);
|
||||
|
||||
if (!_sd_storage_get_op_cond(storage, is_version_1, supports_low_voltage))
|
||||
return 0;
|
||||
DPRINTF("[SD] got op cond\n");
|
||||
|
||||
@@ -1122,7 +1209,7 @@ DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
|
||||
|
||||
if (!storage->is_low_voltage)
|
||||
{
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 6))
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
|
||||
return 0;
|
||||
DPRINTF("[SD] after setup clock\n");
|
||||
}
|
||||
@@ -1165,18 +1252,26 @@ DPRINTF("[SD] SD does not support wide bus width\n");
|
||||
if (!_sd_storage_enable_uhs_low_volt(storage, type, buf))
|
||||
return 0;
|
||||
DPRINTF("[SD] enabled UHS\n");
|
||||
|
||||
sdmmc_card_clock_ctrl(sdmmc, SDMMC_AUTO_CAL_ENABLE);
|
||||
}
|
||||
else if (type != 6 && (storage->scr.sda_vsn & 0xF) != 0)
|
||||
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0)
|
||||
{
|
||||
if (!_sd_storage_enable_hs_high_volt(storage, buf))
|
||||
return 0;
|
||||
|
||||
DPRINTF("[SD] enabled HS\n");
|
||||
storage->csd.busspeed = 25;
|
||||
switch (bus_width)
|
||||
{
|
||||
case SDMMC_BUS_WIDTH_4:
|
||||
storage->csd.busspeed = 25;
|
||||
break;
|
||||
case SDMMC_BUS_WIDTH_1:
|
||||
storage->csd.busspeed = 6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sdmmc_sd_clock_ctrl(sdmmc, 1);
|
||||
|
||||
// Parse additional card info from sd status.
|
||||
if (_sd_storage_get_ssr(storage, buf))
|
||||
{
|
||||
@@ -1222,17 +1317,17 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
|
||||
memset(storage, 0, sizeof(sdmmc_storage_t));
|
||||
storage->sdmmc = sdmmc;
|
||||
|
||||
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, 14, 0))
|
||||
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_DDR52, SDMMC_AUTO_CAL_DISABLE))
|
||||
return 0;
|
||||
DPRINTF("[gc] after init\n");
|
||||
|
||||
usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor);
|
||||
|
||||
if (!sdmmc_config_tuning(storage->sdmmc, 14, MMC_SEND_TUNING_BLOCK_HS200))
|
||||
if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_DDR52, MMC_SEND_TUNING_BLOCK_HS200))
|
||||
return 0;
|
||||
DPRINTF("[gc] after tuning\n");
|
||||
|
||||
sdmmc_sd_clock_ctrl(sdmmc, 1);
|
||||
sdmmc_card_clock_ctrl(sdmmc, SDMMC_AUTO_CAL_ENABLE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,16 @@
|
||||
|
||||
u32 sd_power_cycle_time_start;
|
||||
|
||||
typedef enum _sdmmc_type
|
||||
{
|
||||
MMC_SD = 0,
|
||||
MMC_EMMC = 1,
|
||||
|
||||
EMMC_GPP = 0,
|
||||
EMMC_BOOT0 = 1,
|
||||
EMMC_BOOT1 = 2
|
||||
} sdmmc_type;
|
||||
|
||||
typedef struct _mmc_cid
|
||||
{
|
||||
u32 manfid;
|
||||
@@ -107,10 +117,10 @@ typedef struct _sdmmc_storage_t
|
||||
int sdmmc_storage_end(sdmmc_storage_t *storage);
|
||||
int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type);
|
||||
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
|
||||
int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
|
||||
void sdmmc_storage_init_wait_sd();
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, 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);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-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,
|
||||
@@ -49,24 +50,158 @@
|
||||
#define SDMMC_MASKINT_NOERROR -1
|
||||
#define SDMMC_MASKINT_ERROR -2
|
||||
|
||||
/*! SDMMC host control 2 */
|
||||
#define SDHCI_CTRL_UHS_MASK 0xFFF8
|
||||
#define SDHCI_CTRL_VDD_330 0xFFF7
|
||||
#define SDHCI_CTRL_VDD_180 8
|
||||
#define SDHCI_CTRL_EXEC_TUNING 0x40
|
||||
#define SDHCI_CTRL_TUNED_CLK 0x80
|
||||
#define SDHCI_HOST_VERSION_4_EN 0x1000
|
||||
#define SDHCI_ADDRESSING_64BIT_EN 0x2000
|
||||
#define SDHCI_CTRL_PRESET_VAL_EN 0x8000
|
||||
/*! SDMMC present state. */
|
||||
#define SDHCI_CMD_INHIBIT 0x1
|
||||
#define SDHCI_DATA_INHIBIT 0x2
|
||||
#define SDHCI_DOING_WRITE 0x100
|
||||
#define SDHCI_DOING_READ 0x200
|
||||
#define SDHCI_SPACE_AVAILABLE 0x400
|
||||
#define SDHCI_DATA_AVAILABLE 0x800
|
||||
#define SDHCI_CARD_PRESENT 0x10000
|
||||
#define SDHCI_CD_STABLE 0x20000
|
||||
#define SDHCI_CD_LVL 0x40000
|
||||
#define SDHCI_WRITE_PROTECT 0x80000
|
||||
#define SDHCI_DATA_LVL_MASK 0xF00000
|
||||
#define SDHCI_DATA_0_LVL_MASK 0x100000
|
||||
#define SDHCI_CMD_LVL 0x1000000
|
||||
|
||||
/*! SDMMC transfer mode. */
|
||||
#define SDHCI_TRNS_DMA 0x01
|
||||
#define SDHCI_TRNS_BLK_CNT_EN 0x02
|
||||
#define SDHCI_TRNS_AUTO_CMD12 0x04
|
||||
#define SDHCI_TRNS_AUTO_CMD23 0x08
|
||||
#define SDHCI_TRNS_AUTO_SEL 0x0C
|
||||
#define SDHCI_TRNS_WRITE 0x00
|
||||
#define SDHCI_TRNS_READ 0x10
|
||||
#define SDHCI_TRNS_MULTI 0x20
|
||||
|
||||
/*! SDMMC command. */
|
||||
#define SDHCI_CMD_RESP_MASK 0x3
|
||||
#define SDHCI_CMD_RESP_NO_RESP 0x0
|
||||
#define SDHCI_CMD_RESP_LEN136 0x1
|
||||
#define SDHCI_CMD_RESP_LEN48 0x2
|
||||
#define SDHCI_CMD_RESP_LEN48_BUSY 0x3
|
||||
#define SDHCI_CMD_CRC 0x08
|
||||
#define SDHCI_CMD_INDEX 0x10
|
||||
#define SDHCI_CMD_DATA 0x20
|
||||
#define SDHCI_CMD_ABORTCMD 0xC0
|
||||
|
||||
/*! SDMMC host control. */
|
||||
#define SDHCI_CTRL_LED 0x01
|
||||
#define SDHCI_CTRL_4BITBUS 0x02
|
||||
#define SDHCI_CTRL_HISPD 0x04
|
||||
#define SDHCI_CTRL_DMA_MASK 0x18
|
||||
#define SDHCI_CTRL_SDMA 0x00
|
||||
#define SDHCI_CTRL_ADMA1 0x08
|
||||
#define SDHCI_CTRL_ADMA32 0x10
|
||||
#define SDHCI_CTRL_ADMA64 0x18
|
||||
#define SDHCI_CTRL_8BITBUS 0x20
|
||||
#define SDHCI_CTRL_CDTEST_INS 0x40
|
||||
#define SDHCI_CTRL_CDTEST_EN 0x80
|
||||
|
||||
/*! SDMMC host control 2. */
|
||||
#define SDHCI_CTRL_UHS_MASK 0xFFF8
|
||||
#define SDHCI_CTRL_VDD_180 8
|
||||
#define SDHCI_CTRL_DRV_TYPE_B 0x00
|
||||
#define SDHCI_CTRL_DRV_TYPE_A 0x10
|
||||
#define SDHCI_CTRL_DRV_TYPE_C 0x20
|
||||
#define SDHCI_CTRL_DRV_TYPE_D 0x30
|
||||
#define SDHCI_CTRL_EXEC_TUNING 0x40
|
||||
#define SDHCI_CTRL_TUNED_CLK 0x80
|
||||
#define SDHCI_HOST_VERSION_4_EN 0x1000
|
||||
#define SDHCI_ADDRESSING_64BIT_EN 0x2000
|
||||
#define SDHCI_CTRL_PRESET_VAL_EN 0x8000
|
||||
|
||||
/*! SDMMC power control. */
|
||||
#define SDHCI_POWER_ON 0x01
|
||||
#define SDHCI_POWER_180 0x0A
|
||||
#define SDHCI_POWER_300 0x0C
|
||||
#define SDHCI_POWER_330 0x0E
|
||||
#define SDHCI_POWER_MASK 0xF1
|
||||
|
||||
// /*! SDMMC max current. */
|
||||
// #define SDHCI_MAX_CURRENT_330_MASK 0xFF
|
||||
// #define SDHCI_MAX_CURRENT_180_MASK 0xFF0000
|
||||
// #define SDHCI_MAX_CURRENT_MULTIPLIER 4
|
||||
|
||||
/*! SDMMC clock control. */
|
||||
#define SDHCI_DIVIDER_SHIFT 8
|
||||
#define SDHCI_DIVIDER_HI_SHIFT 6
|
||||
#define SDHCI_DIV_MASK 0xFF00
|
||||
#define SDHCI_DIV_HI_MASK 0xC0
|
||||
#define SDHCI_PROG_CLOCK_MODE 0x20
|
||||
#define SDHCI_CLOCK_CARD_EN 0x4
|
||||
#define SDHCI_CLOCK_INT_STABLE 0x2
|
||||
#define SDHCI_CLOCK_INT_EN 0x1
|
||||
|
||||
/*! SDMMC software reset. */
|
||||
#define SDHCI_RESET_ALL 0x01
|
||||
#define SDHCI_RESET_CMD 0x02
|
||||
#define SDHCI_RESET_DATA 0x04
|
||||
|
||||
/*! SDMMC interrupt status and control. */
|
||||
#define SDHCI_INT_RESPONSE 0x1
|
||||
#define SDHCI_INT_DATA_END 0x2
|
||||
#define SDHCI_INT_BLK_GAP 0x4
|
||||
#define SDHCI_INT_DMA_END 0x8
|
||||
#define SDHCI_INT_SPACE_AVAIL 0x10
|
||||
#define SDHCI_INT_DATA_AVAIL 0x20
|
||||
#define SDHCI_INT_CARD_INSERT 0x40
|
||||
#define SDHCI_INT_CARD_REMOVE 0x80
|
||||
#define SDHCI_INT_CARD_INT 0x100
|
||||
#define SDHCI_INT_RETUNE 0x1000
|
||||
#define SDHCI_INT_CQE 0x4000
|
||||
#define SDHCI_INT_ERROR 0x8000
|
||||
|
||||
/*! SDMMC error interrupt status and control. */
|
||||
#define SDHCI_ERR_INT_TIMEOUT 0x1
|
||||
#define SDHCI_ERR_INT_CRC 0x2
|
||||
#define SDHCI_ERR_INT_END_BIT 0x4
|
||||
#define SDHCI_ERR_INT_INDEX 0x8
|
||||
#define SDHCI_ERR_INT_DATA_TIMEOUT 0x10
|
||||
#define SDHCI_ERR_INT_DATA_CRC 0x20
|
||||
#define SDHCI_ERR_INT_DATA_END_BIT 0x40
|
||||
#define SDHCI_ERR_INT_BUS_POWER 0x80
|
||||
#define SDHCI_ERR_INT_AUTO_CMD_ERR 0x100
|
||||
#define SDHCI_ERR_INT_ADMA_ERROR 0x200
|
||||
|
||||
#define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \
|
||||
(SDHCI_ERR_INT_AUTO_CMD_ERR | SDHCI_ERR_INT_DATA_END_BIT | \
|
||||
SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \
|
||||
SDHCI_ERR_INT_INDEX | SDHCI_ERR_INT_END_BIT | \
|
||||
SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT)
|
||||
|
||||
/*! SD bus speeds. */
|
||||
#define UHS_SDR12_BUS_SPEED 0
|
||||
#define HIGH_SPEED_BUS_SPEED 1
|
||||
#define UHS_SDR25_BUS_SPEED 1
|
||||
#define UHS_SDR50_BUS_SPEED 2
|
||||
#define UHS_SDR104_BUS_SPEED 3
|
||||
#define UHS_DDR50_BUS_SPEED 4
|
||||
#define HS400_BUS_SPEED 5
|
||||
#define UHS_SDR12_BUS_SPEED 0
|
||||
#define HIGH_SPEED_BUS_SPEED 1
|
||||
#define UHS_SDR25_BUS_SPEED 1
|
||||
#define UHS_SDR50_BUS_SPEED 2
|
||||
#define UHS_SDR104_BUS_SPEED 3
|
||||
#define UHS_DDR50_BUS_SPEED 4
|
||||
#define HS400_BUS_SPEED 5
|
||||
|
||||
/*! SDMMC timmings. */
|
||||
#define SDHCI_TIMING_MMC_ID 0
|
||||
#define SDHCI_TIMING_MMC_LS26 1
|
||||
#define SDHCI_TIMING_MMC_HS52 2
|
||||
#define SDHCI_TIMING_MMC_HS200 3
|
||||
#define SDHCI_TIMING_MMC_HS400 4
|
||||
#define SDHCI_TIMING_SD_ID 5
|
||||
#define SDHCI_TIMING_SD_DS12 6
|
||||
#define SDHCI_TIMING_SD_HS25 7
|
||||
#define SDHCI_TIMING_UHS_SDR12 8
|
||||
#define SDHCI_TIMING_UHS_SDR25 9
|
||||
#define SDHCI_TIMING_UHS_SDR50 10
|
||||
#define SDHCI_TIMING_UHS_SDR104 11
|
||||
#define SDHCI_TIMING_UHS_SDR82 12 // SDR104 with a 163.2MHz -> 81.6MHz clock.
|
||||
#define SDHCI_TIMING_UHS_DDR50 13
|
||||
#define SDHCI_TIMING_MMC_DDR52 14
|
||||
|
||||
#define SDHCI_CAN_64BIT 0x10000000
|
||||
|
||||
/*! SDMMC Low power features. */
|
||||
#define SDMMC_AUTO_CAL_DISABLE 0
|
||||
#define SDMMC_AUTO_CAL_ENABLE 1
|
||||
|
||||
/*! Helper for SWITCH command argument. */
|
||||
#define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8))
|
||||
@@ -78,8 +213,8 @@ typedef struct _sdmmc_t
|
||||
u32 id;
|
||||
u32 divisor;
|
||||
u32 clock_stopped;
|
||||
int no_sd;
|
||||
int sd_clock_enabled;
|
||||
int auto_cal_enabled;
|
||||
int card_clock_enabled;
|
||||
int venclkctl_set;
|
||||
u32 venclkctl_tap;
|
||||
u32 expected_rsp_type;
|
||||
@@ -108,19 +243,20 @@ typedef struct _sdmmc_req_t
|
||||
int is_auto_cmd12;
|
||||
} sdmmc_req_t;
|
||||
|
||||
int sdmmc_get_voltage(sdmmc_t *sdmmc);
|
||||
u32 sdmmc_get_bus_width(sdmmc_t *sdmmc);
|
||||
int sdmmc_get_io_power(sdmmc_t *sdmmc);
|
||||
u32 sdmmc_get_bus_width(sdmmc_t *sdmmc);
|
||||
void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width);
|
||||
void sdmmc_get_venclkctl(sdmmc_t *sdmmc);
|
||||
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type);
|
||||
void sdmmc_sd_clock_ctrl(sdmmc_t *sdmmc, int no_sd);
|
||||
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type);
|
||||
int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd);
|
||||
int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp);
|
||||
int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int no_sd);
|
||||
void sdmmc_set_tap_value(sdmmc_t *sdmmc);
|
||||
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type);
|
||||
void sdmmc_card_clock_ctrl(sdmmc_t *sdmmc, int auto_cal_enable);
|
||||
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type);
|
||||
int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd);
|
||||
int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp);
|
||||
bool sdmmc_get_sd_inserted();
|
||||
int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int auto_cal_enable);
|
||||
void sdmmc_end(sdmmc_t *sdmmc);
|
||||
void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy);
|
||||
int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out);
|
||||
int sdmmc_enable_low_voltage(sdmmc_t *sdmmc);
|
||||
int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out);
|
||||
int sdmmc_enable_low_voltage(sdmmc_t *sdmmc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-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,
|
||||
@@ -19,49 +20,14 @@
|
||||
|
||||
#include "../utils/types.h"
|
||||
|
||||
#define TEGRA_MMC_PWRCTL_SD_BUS_POWER 0x1
|
||||
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 0xA
|
||||
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0 0xC
|
||||
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3 0xE
|
||||
#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_MASK 0xF1
|
||||
|
||||
#define TEGRA_MMC_HOSTCTL_1BIT 0x00
|
||||
#define TEGRA_MMC_HOSTCTL_4BIT 0x02
|
||||
#define TEGRA_MMC_HOSTCTL_8BIT 0x20
|
||||
|
||||
#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE 0x1
|
||||
#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE 0x2
|
||||
#define TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE 0x4
|
||||
#define TEGRA_MMC_CLKCON_CLKGEN_SELECT 0x20
|
||||
|
||||
#define TEGRA_MMC_SWRST_SW_RESET_FOR_ALL 0x1
|
||||
#define TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE 0x2
|
||||
#define TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE 0x4
|
||||
|
||||
#define TEGRA_MMC_TRNMOD_DMA_ENABLE 0x1
|
||||
#define TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE 0x2
|
||||
#define TEGRA_MMC_TRNMOD_AUTO_CMD12 0x4
|
||||
#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_WRITE 0x0
|
||||
#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ 0x10
|
||||
#define TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT 0x20
|
||||
|
||||
#define TEGRA_MMC_TRNMOD_CMD_CRC_CHECK 0x8
|
||||
#define TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK 0x10
|
||||
#define TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER 0x20
|
||||
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_MASK 0x3
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE 0x0
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136 0x1
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48 0x2
|
||||
#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY 0x3
|
||||
|
||||
#define TEGRA_MMC_NORINTSTS_CMD_COMPLETE 0x1
|
||||
#define TEGRA_MMC_NORINTSTS_XFER_COMPLETE 0x2
|
||||
#define TEGRA_MMC_NORINTSTS_DMA_INTERRUPT 0x8
|
||||
#define TEGRA_MMC_NORINTSTS_ERR_INTERRUPT 0x8000
|
||||
#define TEGRA_MMC_NORINTSTS_CMD_TIMEOUT 0x10000
|
||||
|
||||
#define TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY 0x20
|
||||
#define TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW 0x20000
|
||||
#define TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE 0x80000000
|
||||
#define TEGRA_MMC_DLLCAL_CFG_STATUS_DLL_ACTIVE 0x80000000
|
||||
#define TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD 0x80000000
|
||||
#define TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK 0xFFFFFFF0
|
||||
#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE 0x20000000
|
||||
#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START 0x80000000
|
||||
#define TEGRA_MMC_AUTOCALSTS_AUTO_CAL_ACTIVE 0x80000000
|
||||
|
||||
typedef struct _t210_sdmmc_t
|
||||
{
|
||||
@@ -77,56 +43,66 @@ typedef struct _t210_sdmmc_t
|
||||
vu32 rspreg3;
|
||||
vu32 bdata;
|
||||
vu32 prnsts;
|
||||
vu8 hostctl;
|
||||
vu8 pwrcon;
|
||||
vu8 blkgap;
|
||||
vu8 wakcon;
|
||||
vu8 hostctl;
|
||||
vu8 pwrcon;
|
||||
vu8 blkgap;
|
||||
vu8 wakcon;
|
||||
vu16 clkcon;
|
||||
vu8 timeoutcon;
|
||||
vu8 swrst;
|
||||
vu8 timeoutcon;
|
||||
vu8 swrst;
|
||||
vu16 norintsts;
|
||||
vu16 errintsts;
|
||||
vu16 norintstsen;
|
||||
vu16 errintstsen;
|
||||
vu16 norintsigen;
|
||||
vu16 errintsigen;
|
||||
vu16 norintstsen; // Enable irq status.
|
||||
vu16 errintstsen; // Enable irq status.
|
||||
vu16 norintsigen; // Enable irq signal to LIC/GIC.
|
||||
vu16 errintsigen; // Enable irq signal to LIC/GIC.
|
||||
vu16 acmd12errsts;
|
||||
vu16 hostctl2;
|
||||
vu32 capareg;
|
||||
vu32 capareg_1;
|
||||
vu32 maxcurr;
|
||||
vu8 res3[4];
|
||||
vu8 rsvd0[4]; // 4C-4F reserved for more max current.
|
||||
vu16 setacmd12err;
|
||||
vu16 setinterr;
|
||||
vu8 admaerr;
|
||||
vu8 res4[3];
|
||||
vu8 admaerr;
|
||||
vu8 rsvd1[3]; // 55-57 reserved.
|
||||
vu32 admaaddr;
|
||||
vu32 admaaddr_hi;
|
||||
vu8 res5[156];
|
||||
vu16 slotintstatus;
|
||||
vu8 rsvd2[156]; // 60-FB reserved.
|
||||
vu16 slotintsts;
|
||||
vu16 hcver;
|
||||
vu32 venclkctl;
|
||||
vu32 venspictl;
|
||||
vu32 venspiintsts;
|
||||
vu32 venceatactl;
|
||||
vu32 vensysswctl;
|
||||
vu32 venerrintsts;
|
||||
vu32 vencapover;
|
||||
vu32 venbootctl;
|
||||
vu32 venbootacktout;
|
||||
vu32 venbootdattout;
|
||||
vu32 vendebouncecnt;
|
||||
vu32 venmiscctl;
|
||||
vu32 res6[34];
|
||||
vu32 maxcurrover;
|
||||
vu32 maxcurrover_hi;
|
||||
vu32 unk0[32]; // 0x12C
|
||||
vu32 veniotrimctl;
|
||||
vu32 vendllcal;
|
||||
vu8 res7[8];
|
||||
vu32 dllcfgstatus;
|
||||
vu32 vendllcalcfg;
|
||||
vu32 vendllctl0;
|
||||
vu32 vendllctl1;
|
||||
vu32 vendllcalcfgsts;
|
||||
vu32 ventunctl0;
|
||||
vu32 field_1C4;
|
||||
vu8 field_1C8[24];
|
||||
vu32 ventunctl1;
|
||||
vu32 ventunsts0;
|
||||
vu32 ventunsts1;
|
||||
vu32 venclkgatehystcnt;
|
||||
vu32 venpresetval0;
|
||||
vu32 venpresetval1;
|
||||
vu32 venpresetval2;
|
||||
vu32 sdmemcmppadctl;
|
||||
vu32 autocalcfg;
|
||||
vu32 autocalintval;
|
||||
vu32 autocalsts;
|
||||
vu32 iospare;
|
||||
vu32 mcciffifoctl;
|
||||
vu32 timeoutwcoal;
|
||||
} t210_sdmmc_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,15 +55,28 @@ typedef int bool;
|
||||
#define BOOT_CFG_AUTOBOOT_EN (1 << 0)
|
||||
#define BOOT_CFG_FROM_LAUNCH (1 << 1)
|
||||
#define BOOT_CFG_FROM_ID (1 << 2)
|
||||
#define BOOT_CFG_TO_EMUMMC (1 << 3)
|
||||
#define BOOT_CFG_SEPT_RUN (1 << 7)
|
||||
|
||||
#define EXTRA_CFG_KEYS (1 << 0)
|
||||
#define EXTRA_CFG_PAYLOAD (1 << 1)
|
||||
#define EXTRA_CFG_MODULE (1 << 2)
|
||||
|
||||
#define EXTRA_CFG_NYX_UMS (1 << 5)
|
||||
#define EXTRA_CFG_NYX_RELOAD (1 << 6)
|
||||
#define EXTRA_CFG_NYX_DUMP (1 << 7)
|
||||
|
||||
typedef enum _nyx_ums_type
|
||||
{
|
||||
NYX_UMS_SD_CARD = 0,
|
||||
NYX_UMS_EMMC_BOOT0,
|
||||
NYX_UMS_EMMC_BOOT1,
|
||||
NYX_UMS_EMMC_GPP,
|
||||
NYX_UMS_EMUMMC_BOOT0,
|
||||
NYX_UMS_EMUMMC_BOOT1,
|
||||
NYX_UMS_EMUMMC_GPP
|
||||
} nyx_ums_type;
|
||||
|
||||
typedef struct __attribute__((__packed__)) _boot_cfg_t
|
||||
{
|
||||
u8 boot_cfg;
|
||||
@@ -74,8 +87,10 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
char id[8];
|
||||
char id[8]; // 7 char ASCII null teminated.
|
||||
char emummc_path[0x78]; // emuMMC/XXX, ASCII null teminated.
|
||||
};
|
||||
u8 ums; // nyx_ums_type.
|
||||
u8 xt_str[0x80];
|
||||
};
|
||||
} boot_cfg_t;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "util.h"
|
||||
#include "../gfx/di.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../mem/minerva.h"
|
||||
#include "../power/max77620.h"
|
||||
#include "../rtc/max77620-rtc.h"
|
||||
@@ -24,13 +25,12 @@
|
||||
#include "../soc/i2c.h"
|
||||
#include "../soc/pmc.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
|
||||
#define USE_RTC_TIMER
|
||||
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
extern void sd_unmount();
|
||||
|
||||
u32 get_tmr_s()
|
||||
{
|
||||
return RTC(APBDEV_RTC_SECONDS);
|
||||
@@ -82,6 +82,43 @@ void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops)
|
||||
base[ops[i].off] = ops[i].val;
|
||||
}
|
||||
|
||||
u32 crc32_calc(u32 crc, const u8 *buf, u32 len)
|
||||
{
|
||||
const u8 *p, *q;
|
||||
static u32 *table = NULL;
|
||||
|
||||
// Calculate CRC table.
|
||||
if (!table)
|
||||
{
|
||||
table = calloc(256, sizeof(u32));
|
||||
for (u32 i = 0; i < 256; i++)
|
||||
{
|
||||
u32 rem = i;
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
{
|
||||
if (rem & 1)
|
||||
{
|
||||
rem >>= 1;
|
||||
rem ^= 0xedb88320;
|
||||
}
|
||||
else
|
||||
rem >>= 1;
|
||||
}
|
||||
table[i] = rem;
|
||||
}
|
||||
}
|
||||
|
||||
crc = ~crc;
|
||||
q = buf + len;
|
||||
for (p = buf; p < q; p++)
|
||||
{
|
||||
u8 oct = *p;
|
||||
crc = (crc >> 8) ^ table[(crc & 0xff) ^ oct];
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
void panic(u32 val)
|
||||
{
|
||||
// Set panic code.
|
||||
@@ -117,7 +154,7 @@ void reboot_rcm()
|
||||
|
||||
nyx_str->mtc_cfg.init_done = 0;
|
||||
|
||||
PMC(APBDEV_PMC_SCRATCH0) = 2; // Reboot into rcm.
|
||||
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM;
|
||||
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
|
||||
|
||||
while (true)
|
||||
@@ -128,6 +165,8 @@ void power_off()
|
||||
{
|
||||
sd_unmount();
|
||||
display_end();
|
||||
|
||||
nyx_str->mtc_cfg.init_done = 0;
|
||||
|
||||
// Stop the alarm, in case we injected and powered off too fast.
|
||||
max77620_rtc_stop_alarm();
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NYX_CFG_UMS = (1 << 6),
|
||||
NYX_CFG_DUMP = (1 << 7),
|
||||
} nyx_cfg_t;
|
||||
|
||||
@@ -31,6 +32,7 @@ typedef enum
|
||||
ERR_LIBSYS_LP0 = (1 << 0),
|
||||
ERR_SYSOLD_NYX = (1 << 1),
|
||||
ERR_SYSOLD_MTC = (1 << 2),
|
||||
ERR_EXCEPT_ENB = (1 << 31),
|
||||
} hekate_errors_t;
|
||||
|
||||
#define byte_swap_32(num) (((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \
|
||||
@@ -44,7 +46,7 @@ typedef struct _cfg_op_t
|
||||
|
||||
typedef struct _nyx_info_t
|
||||
{
|
||||
u32 rsvd;
|
||||
u32 disp_id;
|
||||
u32 errors;
|
||||
} nyx_info_t;
|
||||
|
||||
@@ -70,5 +72,6 @@ void reboot_normal();
|
||||
void reboot_rcm();
|
||||
void power_off();
|
||||
void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops);
|
||||
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,60 +28,74 @@
|
||||
|
||||
/* --- DRAM START --- */
|
||||
#define DRAM_START 0x80000000
|
||||
/* Do not write anything in this area */
|
||||
#define NYX_LOAD_ADDR 0x81000000
|
||||
#define NYX_SZ_MAX 0x1000000
|
||||
/* Stack theoretical max: 220MB */
|
||||
#define IPL_STACK_TOP 0x90010000
|
||||
#define IPL_HEAP_START 0x90020000
|
||||
#define IPL_HEAP_SZ 0x24FE0000 // 592MB.
|
||||
/* --- Gap: 0xB5000000 - 0xB5FFFFFF --- */
|
||||
#define HOS_RSVD 0x1000000 // Do not write anything in this area.
|
||||
|
||||
// SDMMC DMA buffers
|
||||
#define SDXC_BUF_ALIGNED 0xB6000000
|
||||
#define MIXD_BUF_ALIGNED 0xB7000000
|
||||
#define EMMC_BUF_ALIGNED MIXD_BUF_ALIGNED
|
||||
#define SDMMC_DMA_BUF_SZ 0x1000000 // 16MB (4MB currently used).
|
||||
#define SDMMC_UPPER_BUFFER 0xB8000000
|
||||
#define SDMMC_UP_BUF_SZ 0x8000000 // 128MB.
|
||||
#define NYX_LOAD_ADDR 0x81000000
|
||||
#define NYX_SZ_MAX 0x1000000 // 16MB
|
||||
/* --- Gap: 0x82000000 - 0x82FFFFFF --- */
|
||||
|
||||
/* Stack theoretical max: 33MB */
|
||||
#define IPL_STACK_TOP 0x83100000
|
||||
#define IPL_HEAP_START 0x84000000
|
||||
#define IPL_HEAP_SZ 0x20000000 // 512MB.
|
||||
/* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */
|
||||
|
||||
// Virtual disk / Chainloader buffers.
|
||||
#define RAM_DISK_ADDR 0xC1000000
|
||||
#define RAM_DISK_SZ 0x20000000
|
||||
#define RAM_DISK_ADDR 0xA4000000
|
||||
#define RAM_DISK_SZ 0x41000000 // 1040MB.
|
||||
|
||||
//#define DRAM_LIB_ADDR 0xE0000000
|
||||
/* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading.
|
||||
/* --- Gap: 464MB 0xD0000000 - 0xECFFFFFF --- */
|
||||
|
||||
// SDMMC DMA buffers 1
|
||||
#define SDMMC_UPPER_BUFFER 0xE5000000
|
||||
#define SDMMC_UP_BUF_SZ 0x8000000 // 128MB.
|
||||
|
||||
// Nyx buffers.
|
||||
#define NYX_STORAGE_ADDR 0xED000000
|
||||
#define NYX_RES_ADDR 0xEE000000
|
||||
#define NYX_RES_SZ 0x1000000 // 16MB.
|
||||
|
||||
// Framebuffer addresses.
|
||||
#define IPL_FB_ADDRESS 0xF0000000
|
||||
#define IPL_FB_SZ 0x384000 // 720 x 1280 x 4.
|
||||
#define LOG_FB_ADDRESS 0xF0400000
|
||||
#define LOG_FB_SZ 0x334000 // 1280 x 656 x 4.
|
||||
#define NYX_FB_ADDRESS 0xF0800000
|
||||
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
|
||||
// SDMMC DMA buffers 2
|
||||
#define SDXC_BUF_ALIGNED 0xEF000000
|
||||
#define MIXD_BUF_ALIGNED 0xF0000000
|
||||
#define EMMC_BUF_ALIGNED MIXD_BUF_ALIGNED
|
||||
#define SDMMC_DMA_BUF_SZ 0x1000000 // 16MB (4MB currently used).
|
||||
|
||||
// Nyx LvGL buffers.
|
||||
#define NYX_LV_VDB_ADR 0xF0C00000
|
||||
#define NYX_LV_VDB_ADR 0xF1000000
|
||||
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
|
||||
#define NYX_LV_MEM_ADR 0xF1000000
|
||||
#define NYX_LV_MEM_SZ 0x8000000
|
||||
#define NYX_LV_MEM_ADR 0xF1400000
|
||||
#define NYX_LV_MEM_SZ 0x6600000 // 70MB.
|
||||
|
||||
// Framebuffer addresses.
|
||||
#define IPL_FB_ADDRESS 0xF5A00000
|
||||
#define IPL_FB_SZ 0x384000 // 720 x 1280 x 4.
|
||||
#define LOG_FB_ADDRESS 0xF5E00000
|
||||
#define LOG_FB_SZ 0x334000 // 1280 x 656 x 4.
|
||||
#define NYX_FB_ADDRESS 0xF6200000
|
||||
#define NYX_FB2_ADDRESS 0xF6600000
|
||||
#define NYX_FB_SZ 0x384000 // 1280 x 720 x 4.
|
||||
|
||||
#define DRAM_MEM_HOLE_ADR 0xF6A00000
|
||||
#define DRAM_MEM_HOLE_SZ 0x8140000
|
||||
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
|
||||
#define DRAM_START2 0xFEB40000
|
||||
|
||||
// NX BIS driver sector cache.
|
||||
#define NX_BIS_CACHE_ADDR 0xF9000000
|
||||
#define NX_BIS_CACHE_ADDR 0xFEE00000
|
||||
#define NX_BIS_CACHE_SZ 0x8800
|
||||
/* --- Gap: 111MB 0xF9008800 - 0xFFFFFFFF --- */
|
||||
|
||||
// #define EXT_PAYLOAD_ADDR 0xC03C0000
|
||||
// #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
|
||||
// #define COREBOOT_ADDR (0xD0000000 - 0x100000)
|
||||
// USB buffers.
|
||||
#define USBD_ADDR 0xFEF00000
|
||||
#define USB_DESCRIPTOR_ADDR 0xFEF40000
|
||||
#define USB_EP_CONTROL_BUF_ADDR 0xFEF80000
|
||||
#define USB_EP_BULK_IN_BUF_ADDR 0xFF000000
|
||||
#define USB_EP_BULK_OUT_BUF_ADDR 0xFF800000
|
||||
#define USB_EP_BULK_OUT_MAX_XFER 0x800000
|
||||
|
||||
// NYX
|
||||
// #define EXT_PAYLOAD_ADDR 0xC0000000
|
||||
// #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
|
||||
// #define COREBOOT_ADDR (0xD0000000 - 0x100000)
|
||||
// #define COREBOOT_ADDR (0xD0000000 - rom_size)
|
||||
|
||||
#endif
|
||||
|
||||
16
nyx/Makefile
16
nyx/Makefile
@@ -21,20 +21,22 @@ VPATH += $(dir $(wildcard ./$(SOURCEDIR)/*/*/*/)) $(dir $(wildcard ./$(SOURCEDIR
|
||||
|
||||
# Main and graphics.
|
||||
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
start.o \
|
||||
start.o exception_handlers.o \
|
||||
nyx.o heap.o \
|
||||
gfx.o \
|
||||
gui.o gui_info.o gui_tools.o gui_options.o gui_emmc_tools.o gui_emummc_tools.o \
|
||||
gui.o gui_info.o gui_tools.o gui_options.o gui_emmc_tools.o gui_emummc_tools.o gui_tools_partition_manager.o \
|
||||
fe_emummc_tools.o fe_emmc_tools.o \
|
||||
)
|
||||
|
||||
# Hardware.
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
bpmp.o clock.o cluster.o di.o gpio.o i2c.o mc.o sdram.o pinmux.o se.o smmu.o tsec.o uart.o \
|
||||
fuse.o kfuse.o minerva.o \
|
||||
sdmmc.o sdmmc_driver.o \
|
||||
bpmp.o clock.o cluster.o di.o gpio.o i2c.o irq.o pinmux.o se.o smmu.o tsec.o uart.o \
|
||||
fuse.o kfuse.o \
|
||||
mc.o sdram.o minerva.o ramdisk.o \
|
||||
sdmmc.o sdmmc_driver.o nx_emmc.o nx_emmc_bis.o nx_sd.o \
|
||||
bq24193.o max17050.o max7762x.o max77620-rtc.o regulator_5v.o \
|
||||
touch.o tmp451.o fan.o \
|
||||
touch.o joycon.o tmp451.o fan.o \
|
||||
usbd.o usb_gadget_ums.o usb_gadget_hid.o \
|
||||
hw_init.o \
|
||||
)
|
||||
|
||||
@@ -54,7 +56,7 @@ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
# Libraries.
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
diskio.o ff.o ffunicode.o ffsystem.o \
|
||||
elfload.o elfreloc_arm.o \
|
||||
elfload.o elfreloc_arm.o blz.o \
|
||||
lv_group.o lv_indev.o lv_obj.o lv_refr.o lv_style.o lv_vdb.o \
|
||||
lv_draw.o lv_draw_rbasic.o lv_draw_vbasic.o lv_draw_arc.o lv_draw_img.o \
|
||||
lv_draw_label.o lv_draw_line.o lv_draw_rect.o lv_draw_triangle.o \
|
||||
|
||||
@@ -23,21 +23,20 @@
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/list.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount(bool deinit);
|
||||
extern nyx_config n_cfg;
|
||||
|
||||
void set_default_configuration()
|
||||
{
|
||||
h_cfg.autoboot = 0;
|
||||
h_cfg.autoboot_list = 0;
|
||||
h_cfg.bootwait = 3;
|
||||
h_cfg.verification = 1;
|
||||
h_cfg.se_keygen_done = 0;
|
||||
h_cfg.sbar_time_keeping = 0;
|
||||
h_cfg.backlight = 100;
|
||||
@@ -47,6 +46,7 @@ void set_default_configuration()
|
||||
h_cfg.brand = NULL;
|
||||
h_cfg.tagline = NULL;
|
||||
h_cfg.errors = 0;
|
||||
h_cfg.eks = NULL;
|
||||
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
|
||||
h_cfg.rcm_patched = fuse_check_patched_rcm();
|
||||
h_cfg.emummc_force_disable = false;
|
||||
@@ -54,6 +54,14 @@ void set_default_configuration()
|
||||
sd_power_cycle_time_start = 0;
|
||||
}
|
||||
|
||||
void set_nyx_default_configuration()
|
||||
{
|
||||
n_cfg.themecolor = 167;
|
||||
n_cfg.timeoff = 0;
|
||||
n_cfg.home_screen = 0;
|
||||
n_cfg.verification = 1;
|
||||
}
|
||||
|
||||
int create_config_entry()
|
||||
{
|
||||
if (!sd_mount())
|
||||
@@ -97,9 +105,6 @@ int create_config_entry()
|
||||
f_puts("\nbootwait=", &fp);
|
||||
itoa(h_cfg.bootwait, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nverification=", &fp);
|
||||
itoa(h_cfg.verification, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nbacklight=", &fp);
|
||||
itoa(h_cfg.backlight, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
@@ -170,3 +175,37 @@ int create_config_entry()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int create_nyx_config_entry()
|
||||
{
|
||||
if (!sd_mount())
|
||||
return 1;
|
||||
|
||||
char lbuf[32];
|
||||
FIL fp;
|
||||
|
||||
// Make sure that bootloader folder exists.
|
||||
f_mkdir("bootloader");
|
||||
|
||||
if (f_open(&fp, "bootloader/nyx.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
|
||||
return 1;
|
||||
|
||||
// Add config entry.
|
||||
f_puts("[config]\nthemecolor=", &fp);
|
||||
itoa(n_cfg.themecolor, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\ntimeoff=", &fp);
|
||||
itoa(n_cfg.timeoff, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nhomescreen=", &fp);
|
||||
itoa(n_cfg.home_screen, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\nverification=", &fp);
|
||||
itoa(n_cfg.verification, lbuf, 10);
|
||||
f_puts(lbuf, &fp);
|
||||
f_puts("\n", &fp);
|
||||
|
||||
f_close(&fp);
|
||||
sd_unmount(false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#include "../hos/hos.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
typedef struct _hekate_config
|
||||
@@ -25,7 +26,6 @@ typedef struct _hekate_config
|
||||
u32 autoboot;
|
||||
u32 autoboot_list;
|
||||
u32 bootwait;
|
||||
u32 verification;
|
||||
u32 backlight;
|
||||
u32 autohosoff;
|
||||
u32 autonogc;
|
||||
@@ -39,9 +39,20 @@ typedef struct _hekate_config
|
||||
bool rcm_patched;
|
||||
u32 sbar_time_keeping;
|
||||
u32 errors;
|
||||
hos_eks_mbr_t *eks;
|
||||
} hekate_config;
|
||||
|
||||
typedef struct _nyx_config
|
||||
{
|
||||
u32 themecolor;
|
||||
s32 timeoff;
|
||||
u32 home_screen;
|
||||
u32 verification;
|
||||
} nyx_config;
|
||||
|
||||
void set_default_configuration();
|
||||
void set_nyx_default_configuration();
|
||||
int create_config_entry();
|
||||
int create_nyx_config_entry();
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
||||
|
||||
@@ -55,12 +55,9 @@ u32 _find_section_name(char *lbuf, u32 lblen, char schar)
|
||||
ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type)
|
||||
{
|
||||
if (csec)
|
||||
{
|
||||
list_append(dst, &csec->link);
|
||||
csec = NULL;
|
||||
}
|
||||
|
||||
csec = (ini_sec_t *)malloc(sizeof(ini_sec_t));
|
||||
csec = (ini_sec_t *)calloc(sizeof(ini_sec_t), 1);
|
||||
csec->name = _strdup(name);
|
||||
csec->type = type;
|
||||
|
||||
@@ -154,7 +151,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir)
|
||||
{
|
||||
u32 i = _find_section_name(lbuf, lblen, '=');
|
||||
|
||||
ini_kv_t *kv = (ini_kv_t *)malloc(sizeof(ini_kv_t));
|
||||
ini_kv_t *kv = (ini_kv_t *)calloc(sizeof(ini_kv_t), 1);
|
||||
kv->key = _strdup(&lbuf[0]);
|
||||
kv->val = _strdup(&lbuf[i + 1]);
|
||||
list_append(&csec->kvs, &kv->link);
|
||||
|
||||
233
nyx/nyx_gui/exception_handlers.S
Normal file
233
nyx/nyx_gui/exception_handlers.S
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Armv7tdmi Status register.
|
||||
*
|
||||
* bit0: Mode 0.
|
||||
* bit1: Mode 1.
|
||||
* bit2: Mode 2.
|
||||
* bit3: Mode 3.
|
||||
* bit4: Mode 4.
|
||||
* bit5: Thumb state.
|
||||
* bit6: FIQ disable.
|
||||
* bit7: IRQ disable.
|
||||
* bit8-27: Reserved.
|
||||
* bit28: Overflow condition.
|
||||
* bit29: Carry/Borrow/Extend condition.
|
||||
* bit30: Zero condition.
|
||||
* bit31: Negative/Less than condition.
|
||||
*
|
||||
* M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers
|
||||
* 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||
* 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq
|
||||
* 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq
|
||||
* 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc
|
||||
* 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
|
||||
* 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und
|
||||
* 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||
*/
|
||||
|
||||
#define EXCP_EN_ADDR 0x4003FFFC
|
||||
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||||
#define EXCP_LR_ADDR 0x4003FFF4
|
||||
|
||||
#define EXCP_VEC_BASE 0x6000F000
|
||||
#define EVP_COP_RESET_VECTOR 0x200
|
||||
#define EVP_COP_UNDEF_VECTOR 0x204
|
||||
#define EVP_COP_SWI_VECTOR 0x208
|
||||
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
|
||||
#define EVP_COP_DATA_ABORT_VECTOR 0x210
|
||||
#define EVP_COP_RSVD_VECTOR 0x214
|
||||
#define EVP_COP_IRQ_VECTOR 0x218
|
||||
#define EVP_COP_FIQ_VECTOR 0x21C
|
||||
|
||||
#define MODE_USR 0x10
|
||||
#define MODE_FIQ 0x11
|
||||
#define MODE_IRQ 0x12
|
||||
#define MODE_SVC 0x13
|
||||
#define MODE_ABT 0x17
|
||||
#define MODE_UDF 0x1B
|
||||
#define MODE_SYS 0x1F
|
||||
#define MODE_MASK 0x1F
|
||||
|
||||
#define FIQ 0x40
|
||||
#define IRQ 0x80
|
||||
|
||||
.section .text._irq_setup
|
||||
.arm
|
||||
|
||||
.extern ipl_main
|
||||
.type ipl_main, %function
|
||||
|
||||
.extern svc_handler
|
||||
.type svc_handler, %function
|
||||
|
||||
.extern irq_handler
|
||||
.type irq_handler, %function
|
||||
|
||||
.extern fiq_setup
|
||||
.type fiq_setup, %function
|
||||
|
||||
.extern fiq_handler
|
||||
.type fiq_handler, %function
|
||||
|
||||
.globl _irq_setup
|
||||
.type _irq_setup, %function
|
||||
_irq_setup:
|
||||
MRS R0, CPSR
|
||||
BIC R0, R0, #MODE_MASK /* Clear mode bits */
|
||||
ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */
|
||||
MSR CPSR, R0
|
||||
|
||||
/* Setup IRQ stack pointer */
|
||||
MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||
LDR SP, =0x40040000
|
||||
|
||||
/* Setup SYS stack pointer */
|
||||
MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||
LDR SP, =0x4003FF00 /* Will be changed later to DRAM */
|
||||
|
||||
MOV LR, PC
|
||||
BL setup_vectors
|
||||
/*BL fiq_setup*/
|
||||
|
||||
/* Enable interrupts */
|
||||
BL irq_enable_cpu_irq_exceptions
|
||||
|
||||
B ipl_main
|
||||
B .
|
||||
|
||||
_reset:
|
||||
LDR R0, =EXCP_EN_ADDR
|
||||
LDR R1, =0x30505645 /* EVP0 */
|
||||
STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */
|
||||
LDR R0, =EXCP_LR_ADDR
|
||||
MOV R1, LR
|
||||
STR R1, [R0] /* Save LR in EXCP_LR_ADDR */
|
||||
LDR R0, =__bss_start
|
||||
EOR R1, R1, R1
|
||||
LDR R2, =__bss_end
|
||||
SUB R2, R2, R0
|
||||
BL memset
|
||||
B _irq_setup
|
||||
|
||||
_reset_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x545352 /* RST */
|
||||
STR R1, [R0] /* RST in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
_undefined_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x464455 /* UDF */
|
||||
STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
_prefetch_abort_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x54424150 /* PABT */
|
||||
STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
_data_abort_handler:
|
||||
LDR R0, =EXCP_TYPE_ADDR
|
||||
LDR R1, =0x54424144 /* DABT */
|
||||
STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
|
||||
B _reset
|
||||
|
||||
.globl irq_enable_cpu_irq_exceptions
|
||||
.type irq_enable_cpu_irq_exceptions, %function
|
||||
irq_enable_cpu_irq_exceptions:
|
||||
MRS R12, CPSR
|
||||
BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */
|
||||
MSR CPSR, R12
|
||||
BX LR
|
||||
|
||||
.globl irq_disable_cpu_irq_exceptions
|
||||
.type irq_disable_cpu_irq_exceptions, %function
|
||||
irq_disable_cpu_irq_exceptions:
|
||||
MRS R12, CPSR
|
||||
ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */
|
||||
MSR CPSR, R12
|
||||
BX LR
|
||||
|
||||
_irq_handler:
|
||||
MOV R13, R0 /* Save R0 in R13_IRQ */
|
||||
SUB R0, LR, #4 /* Put return address in R0_SYS */
|
||||
MOV LR, R1 /* Save R1 in R14_IRQ (LR) */
|
||||
MRS R1, SPSR /* Put the SPSR in R1_SYS */
|
||||
|
||||
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||
STMFD SP!, {R0, R1} /* SPSR and PC */
|
||||
STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */
|
||||
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||
SUB SP, SP, #8 /* Make room for stacking R0 and R1 */
|
||||
|
||||
MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */
|
||||
STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */
|
||||
|
||||
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||
LDR R12, =irq_handler
|
||||
MOV LR, PC /* Copy the return address to link register */
|
||||
BX R12 /* Call the C IRQ handler (ARM/THUMB) */
|
||||
|
||||
MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||
ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */
|
||||
|
||||
MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||
MOV SP, R0 /* Copy SP_SYS to SP_IRQ */
|
||||
LDR R0, [SP, #28] /* Load the saved SPSR from the stack */
|
||||
MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */
|
||||
|
||||
LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */
|
||||
NOP /* Cant access barked registers immediately */
|
||||
LDR LR, [SP, #24] /* Load return address from the SYS stack */
|
||||
MOVS PC, LR /* Return restoring CPSR from SPSR */
|
||||
|
||||
_fiq_handler:
|
||||
BL fiq_handler
|
||||
|
||||
setup_vectors:
|
||||
/* Setup vectors */
|
||||
LDR R0, =EXCP_VEC_BASE
|
||||
|
||||
LDR R1, =_reset_handler
|
||||
STR R1, [R0, #EVP_COP_RESET_VECTOR]
|
||||
|
||||
LDR R1, =_undefined_handler
|
||||
STR R1, [R0, #EVP_COP_UNDEF_VECTOR]
|
||||
|
||||
LDR R1, =_reset_handler
|
||||
STR R1, [R0, #EVP_COP_SWI_VECTOR]
|
||||
|
||||
LDR R1, =_prefetch_abort_handler
|
||||
STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR]
|
||||
|
||||
LDR R1, =_data_abort_handler
|
||||
STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR]
|
||||
|
||||
LDR R1, =_reset_handler
|
||||
STR R1, [R0, #EVP_COP_RSVD_VECTOR]
|
||||
|
||||
LDR R1, =_irq_handler
|
||||
STR R1, [R0, #EVP_COP_IRQ_VECTOR]
|
||||
|
||||
LDR R1, =_fiq_handler
|
||||
STR R1, [R0, #EVP_COP_FIQ_VECTOR]
|
||||
|
||||
BX LR
|
||||
@@ -30,7 +30,9 @@
|
||||
#include "../mem/heap.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../sec/se_t210.h"
|
||||
#include "../storage/mbr_gpt.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/sprintf.h"
|
||||
@@ -41,34 +43,48 @@
|
||||
#define HASH_FILENAME_SZ (OUT_FILENAME_SZ + 11) // 11 == strlen(".sha256sums")
|
||||
#define SHA256_SZ 0x20
|
||||
|
||||
extern sdmmc_t sd_sdmmc;
|
||||
extern sdmmc_storage_t sd_storage;
|
||||
extern FATFS sd_fs;
|
||||
extern hekate_config h_cfg;
|
||||
extern nyx_config n_cfg;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount(bool deinit);
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
static void get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_idx, bool backup)
|
||||
static void _get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_idx, bool backup)
|
||||
{
|
||||
sd_mount();
|
||||
u8 *mbr = (u8 *)malloc(0x200);
|
||||
mbr_t *mbr = (mbr_t *)calloc(sizeof(mbr_t), 1);
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
|
||||
memcpy(mbr, mbr + 0x1BE, 0x40);
|
||||
|
||||
*part_idx = 0;
|
||||
int i = 0;
|
||||
u32 curr_part_size = 0;
|
||||
for (i = 1; i < 4; i++)
|
||||
{
|
||||
curr_part_size = *(u32 *)&mbr[0x0C + (0x10 * i)];
|
||||
*sector_start = *(u32 *)&mbr[0x08 + (0x10 * i)];
|
||||
u8 type = mbr[0x04 + (0x10 * i)];
|
||||
curr_part_size = mbr->partitions[i].size_sct;
|
||||
*sector_start = mbr->partitions[i].start_sct;
|
||||
u8 type = mbr->partitions[i].type;
|
||||
if ((curr_part_size >= *sector_size) && *sector_start && type != 0x83 && (!backup || type == 0xE0))
|
||||
break;
|
||||
{
|
||||
if (backup)
|
||||
{
|
||||
u8 gpt_check[512] = { 0 };
|
||||
sdmmc_storage_read(&sd_storage, *sector_start + 0xC001, 1, gpt_check);
|
||||
if (!memcmp(gpt_check, "EFI PART", 8))
|
||||
{
|
||||
*sector_size = curr_part_size;
|
||||
*sector_start = *sector_start + 0x8000;
|
||||
break;
|
||||
}
|
||||
sdmmc_storage_read(&sd_storage, *sector_start + 0x4001, 1, gpt_check);
|
||||
if (!memcmp(gpt_check, "EFI PART", 8))
|
||||
{
|
||||
*sector_size = curr_part_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < 4)
|
||||
*part_idx = i;
|
||||
else
|
||||
@@ -76,34 +92,24 @@ static void get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_i
|
||||
*sector_start = 0;
|
||||
*sector_size = 0;
|
||||
*part_idx = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!backup)
|
||||
*sector_start = *sector_start + 0x8000;
|
||||
else
|
||||
{
|
||||
*sector_size = curr_part_size;
|
||||
sdmmc_storage_read(&sd_storage, *sector_start + 0xC001, 1, mbr);
|
||||
if (!memcmp(mbr, "EFI PART", 8))
|
||||
{
|
||||
*sector_start = *sector_start + 0x8000;
|
||||
goto out;
|
||||
}
|
||||
sdmmc_storage_read(&sd_storage, *sector_start + 0x4001, 1, mbr);
|
||||
if (!memcmp(mbr, "EFI PART", 8))
|
||||
goto out;
|
||||
|
||||
sdmmc_storage_read(&sd_storage, *sector_start + 0x4003, 1, mbr);
|
||||
if (!memcmp(mbr, "EFI PART", 8))
|
||||
{
|
||||
*sector_start = *sector_start + 2;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
free(mbr);
|
||||
if (backup && *part_idx && *sector_size)
|
||||
{
|
||||
gpt_t *gpt = (gpt_t *)calloc(sizeof(gpt_t), 1);
|
||||
sdmmc_storage_read(&sd_storage, *sector_start + 0x4001, 1, gpt);
|
||||
|
||||
u32 new_size = gpt->header.alt_lba + 1;
|
||||
if (*sector_size > new_size)
|
||||
*sector_size = new_size;
|
||||
else
|
||||
*sector_size = 0;
|
||||
|
||||
free(gpt);
|
||||
}
|
||||
else if (!backup && *part_idx)
|
||||
*sector_start = *sector_start + 0x8000;
|
||||
}
|
||||
|
||||
static lv_obj_t *create_mbox_text(char *text, bool button_ok)
|
||||
@@ -154,7 +160,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
|
||||
if (f_open(&fp, outFilename, FA_READ) == FR_OK)
|
||||
{
|
||||
if (h_cfg.verification == 3)
|
||||
if (n_cfg.verification == 3)
|
||||
{
|
||||
char hashFilename[HASH_FILENAME_SZ];
|
||||
strncpy(hashFilename, outFilename, OUT_FILENAME_SZ - 1);
|
||||
@@ -166,7 +172,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
f_close(&fp);
|
||||
|
||||
s_printf(gui->txt_buf,
|
||||
"#FF0000 Hash file could not be written (error %d)!#\n"
|
||||
"\n#FF0000 Hash file could not be written (error %d)!#\n"
|
||||
"#FF0000 Aborting..#\n", res);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
@@ -191,7 +197,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
u32 pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start);
|
||||
lv_bar_set_value(gui->bar, pct);
|
||||
lv_bar_set_style(gui->bar, LV_BAR_STYLE_BG, gui->bar_teal_bg);
|
||||
lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, lv_theme_get_current()->bar.indic);
|
||||
lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, gui->bar_teal_ind);
|
||||
s_printf(gui->txt_buf, " "SYMBOL_DOT" %d%%", pct);
|
||||
lv_label_set_text(gui->label_pct, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
@@ -206,12 +212,12 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
// Check every time or every 4.
|
||||
// Every 4 protects from fake sd, sector corruption and frequent I/O corruption.
|
||||
// Full provides all that, plus protection from extremely rare I/O corruption.
|
||||
if ((h_cfg.verification >= 2) || !(sparseShouldVerify % 4))
|
||||
if ((n_cfg.verification >= 2) || !(sparseShouldVerify % 4))
|
||||
{
|
||||
if (!sdmmc_storage_read(storage, lba_curr, num, bufEm))
|
||||
{
|
||||
s_printf(gui->txt_buf,
|
||||
"#FF0000 Failed to read %d blocks (@LBA %08X),#\n"
|
||||
"\n#FF0000 Failed to read %d blocks (@LBA %08X),#\n"
|
||||
"#FF0000 from eMMC! Verification failed..#\n",
|
||||
num, lba_curr);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
@@ -219,7 +225,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
|
||||
free(clmt);
|
||||
f_close(&fp);
|
||||
if (h_cfg.verification == 3)
|
||||
if (n_cfg.verification == 3)
|
||||
f_close(&hashFp);
|
||||
|
||||
return 1;
|
||||
@@ -231,7 +237,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
if (f_read_fast(&fp, bufSd, num << 9))
|
||||
{
|
||||
s_printf(gui->txt_buf,
|
||||
"#FF0000 Failed to read %d blocks (@LBA %08X),#\n"
|
||||
"\n#FF0000 Failed to read %d blocks (@LBA %08X),#\n"
|
||||
"#FF0000 from SD card! Verification failed..#\n",
|
||||
num, lba_curr);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
@@ -239,7 +245,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
|
||||
free(clmt);
|
||||
f_close(&fp);
|
||||
if (h_cfg.verification == 3)
|
||||
if (n_cfg.verification == 3)
|
||||
f_close(&hashFp);
|
||||
|
||||
return 1;
|
||||
@@ -252,7 +258,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
if (res)
|
||||
{
|
||||
s_printf(gui->txt_buf,
|
||||
"#FF0000 SD & eMMC data (@LBA %08X) do not match!#\n"
|
||||
"\n#FF0000 SD & eMMC data (@LBA %08X) do not match!#\n"
|
||||
"\n#FF0000 Verification failed..#\n",
|
||||
lba_curr);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
@@ -260,13 +266,13 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
|
||||
free(clmt);
|
||||
f_close(&fp);
|
||||
if (h_cfg.verification == 3)
|
||||
if (n_cfg.verification == 3)
|
||||
f_close(&hashFp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (h_cfg.verification == 3)
|
||||
if (n_cfg.verification == 3)
|
||||
{
|
||||
// Transform computed hash to readable hexadecimal
|
||||
char hashStr[SHA256_SZ * 2 + 1];
|
||||
@@ -289,6 +295,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
lv_bar_set_value(gui->bar, pct);
|
||||
s_printf(gui->txt_buf, " "SYMBOL_DOT" %d%%", pct);
|
||||
lv_label_set_text(gui->label_pct, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
prevPct = pct;
|
||||
}
|
||||
|
||||
@@ -338,7 +345,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
|
||||
bool partial_sd_full_unmount = false;
|
||||
|
||||
static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
{
|
||||
const u32 FAT32_FILESIZE_LIMIT = 0xFFFFFFFF;
|
||||
const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
@@ -356,10 +363,30 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_storage_t
|
||||
char *outFilename = sd_path;
|
||||
u32 sdPathLen = strlen(sd_path);
|
||||
|
||||
u32 sector_start = 0, part_idx = 0;
|
||||
u32 sector_size = totalSectors;
|
||||
u32 sd_sector_off = 0;
|
||||
|
||||
FIL partialIdxFp;
|
||||
char partialIdxFilename[12];
|
||||
strcpy(partialIdxFilename, "partial.idx");
|
||||
|
||||
if (gui->raw_emummc)
|
||||
{
|
||||
_get_valid_partition(§or_start, §or_size, &part_idx, true);
|
||||
if (!part_idx || !sector_size)
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FFDD00 Failed to find a partition...#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
sd_sector_off = sector_start + (0x2000 * active_part);
|
||||
if (active_part == 2)
|
||||
totalSectors = sector_size;
|
||||
}
|
||||
|
||||
s_printf(gui->txt_buf, "#96FF00 SD Card free space:# %d MiB\n#96FF00 Total backup size:# %d MiB\n\n",
|
||||
sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF,
|
||||
totalSectors >> SECTORS_TO_MIB_COEFF);
|
||||
@@ -510,7 +537,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_storage_t
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
currPartIdx++;
|
||||
|
||||
if (h_cfg.verification)
|
||||
if (n_cfg.verification && !gui->raw_emummc)
|
||||
{
|
||||
// Verify part.
|
||||
if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
|
||||
@@ -588,7 +615,14 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_storage_t
|
||||
|
||||
retryCount = 0;
|
||||
num = MIN(totalSectors, NUM_SECTORS_PER_ITER);
|
||||
while (!sdmmc_storage_read(storage, lba_curr, num, buf))
|
||||
|
||||
int res_read;
|
||||
if (!gui->raw_emummc)
|
||||
res_read = !sdmmc_storage_read(storage, lba_curr, num, buf);
|
||||
else
|
||||
res_read = !sdmmc_storage_read(&sd_storage, lba_curr + sd_sector_off, num, buf);
|
||||
|
||||
while (res_read)
|
||||
{
|
||||
s_printf(gui->txt_buf,
|
||||
"\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
|
||||
@@ -682,7 +716,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_storage_t
|
||||
f_close(&fp);
|
||||
free(clmt);
|
||||
|
||||
if (h_cfg.verification)
|
||||
if (n_cfg.verification && !gui->raw_emummc)
|
||||
{
|
||||
// Verify last part or single file backup.
|
||||
if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
|
||||
@@ -718,18 +752,18 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
int res = 0;
|
||||
u32 timer = 0;
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
gui->txt_buf = txt_buf;
|
||||
|
||||
s_printf(txt_buf, "");
|
||||
lv_label_set_text(gui->label_log, txt_buf);
|
||||
|
||||
lv_label_set_static_text(gui->label_info, "Checking for available free space...");
|
||||
lv_label_set_text(gui->label_info, "Checking for available free space...");
|
||||
manual_system_maintenance(true);
|
||||
|
||||
if (!sd_mount())
|
||||
{
|
||||
lv_label_set_static_text(gui->label_info, "#FFDD00 Failed to init SD!#");
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -738,9 +772,9 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_static_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -778,7 +812,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
sdmmc_storage_set_mmc_partition(&storage, i + 1);
|
||||
|
||||
emmcsn_path_impl(sdPath, "", bootPart.name, &storage);
|
||||
res = _dump_emmc_part(gui, sdPath, &storage, &bootPart);
|
||||
res = _dump_emmc_part(gui, sdPath, i, &storage, &bootPart);
|
||||
|
||||
if (!res)
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
@@ -792,7 +826,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
|
||||
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER) || (dumpType & PART_RAW))
|
||||
{
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER))
|
||||
{
|
||||
@@ -818,7 +852,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
i++;
|
||||
|
||||
emmcsn_path_impl(sdPath, "/partitions", part->name, &storage);
|
||||
res = _dump_emmc_part(gui, sdPath, &storage, part);
|
||||
res = _dump_emmc_part(gui, sdPath, 0, &storage, part);
|
||||
// If a part failed, don't continue.
|
||||
if (!res)
|
||||
{
|
||||
@@ -856,7 +890,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
i++;
|
||||
|
||||
emmcsn_path_impl(sdPath, "", rawPart.name, &storage);
|
||||
res = _dump_emmc_part(gui, sdPath, &storage, &rawPart);
|
||||
res = _dump_emmc_part(gui, sdPath, 2, &storage, &rawPart);
|
||||
|
||||
if (!res)
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
@@ -872,7 +906,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
timer = get_tmr_s() - timer;
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
if (res && h_cfg.verification)
|
||||
if (res && n_cfg.verification && !gui->raw_emummc)
|
||||
s_printf(txt_buf, "Time taken: %dm %ds.\n#96FF00 Finished and verified!#", timer / 60, timer % 60);
|
||||
else if (res)
|
||||
s_printf(txt_buf, "Time taken: %dm %ds.\nFinished!", timer / 60, timer % 60);
|
||||
@@ -986,17 +1020,27 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||
|
||||
if ((u32)((u64)totalCheckFileSize >> (u64)9) != totalSectors)
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FF0000 Size of SD Card split backup does not match,#\n#FF0000 eMMC's selected part size!#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
lv_obj_t *warn_mbox_bg = create_mbox_text(
|
||||
"#FF8000 Size of SD Card split backup does not match,#\n#FF8000 eMMC's selected part size!#\n\n"
|
||||
"#FFDD00 Your backup might be corrupted!#\n#FFDD00 Aborting is suggested!#\n\n"
|
||||
"Press #FF8000 POWER# to Continue.\nPress #FF8000 VOL# to abort.", false);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
use_multipart = true;
|
||||
_update_filename(outFilename, sdPathLen, 0);
|
||||
if (!(btn_wait() & BTN_POWER))
|
||||
{
|
||||
lv_obj_del(warn_mbox_bg);
|
||||
s_printf(gui->txt_buf, "#FF0000 Size of SD Card split backup does not match,#\n#FF0000 eMMC's selected part size!#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
lv_obj_del(warn_mbox_bg);
|
||||
|
||||
totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9);
|
||||
}
|
||||
use_multipart = true;
|
||||
_update_filename(outFilename, sdPathLen, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1038,16 +1082,26 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||
{
|
||||
if (!gui->raw_emummc)
|
||||
{
|
||||
s_printf(gui->txt_buf, "\n#FF0000 Size of the SD Card backup does not match,#\n#FF0000 eMMC's selected part size.#\n", res);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
lv_obj_t *warn_mbox_bg = create_mbox_text(
|
||||
"#FF8000 Size of the SD Card backup does not match,#\n#FF8000 eMMC's selected part size!#\n\n"
|
||||
"#FFDD00 Your backup might be corrupted!#\n#FFDD00 Aborting is suggested!#\n\n"
|
||||
"Press #FF8000 POWER# to Continue.\nPress #FF8000 VOL# to abort.", false);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
f_close(&fp);
|
||||
if (!(btn_wait() & BTN_POWER))
|
||||
{
|
||||
lv_obj_del(warn_mbox_bg);
|
||||
s_printf(gui->txt_buf, "\n#FF0000 Size of the SD Card backup does not match,#\n#FF0000 eMMC's selected part size.#\n", res);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
return 0;
|
||||
f_close(&fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
lv_obj_del(warn_mbox_bg);
|
||||
}
|
||||
else
|
||||
totalSectors = (u32)((u64)f_size(&fp) >> (u64)9);
|
||||
totalSectors = (u32)((u64)f_size(&fp) >> (u64)9);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1076,8 +1130,8 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||
|
||||
if (gui->raw_emummc)
|
||||
{
|
||||
get_valid_partition(§or_start, §or_size, &part_idx, false);
|
||||
if (!part_idx)
|
||||
_get_valid_partition(§or_start, §or_size, &part_idx, false);
|
||||
if (!part_idx || !sector_size)
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FFDD00 Failed to find a partition...#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
@@ -1101,7 +1155,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
currPartIdx++;
|
||||
|
||||
if (h_cfg.verification && !gui->raw_emummc)
|
||||
if (n_cfg.verification && !gui->raw_emummc)
|
||||
{
|
||||
// Verify part.
|
||||
if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
|
||||
@@ -1223,7 +1277,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||
f_close(&fp);
|
||||
free(clmt);
|
||||
|
||||
if (h_cfg.verification && !gui->raw_emummc)
|
||||
if (n_cfg.verification && !gui->raw_emummc)
|
||||
{
|
||||
// Verify restored data.
|
||||
if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
|
||||
@@ -1264,7 +1318,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
int res = 0;
|
||||
u32 timer = 0;
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
gui->txt_buf = txt_buf;
|
||||
|
||||
s_printf(txt_buf, "");
|
||||
@@ -1301,10 +1355,9 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
lv_mbox_set_text(warn_mbox, txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (!(btn & BTN_POWER))
|
||||
if (!(btn_wait() & BTN_POWER))
|
||||
{
|
||||
lv_label_set_static_text(gui->label_info, "#FFDD00 Restore operation was aborted!#");
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Restore operation was aborted!#");
|
||||
lv_obj_del(warn_mbox_bg);
|
||||
goto out;
|
||||
}
|
||||
@@ -1313,15 +1366,15 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
|
||||
if (!sd_mount())
|
||||
{
|
||||
lv_label_set_static_text(gui->label_info, "#FFDD00 Failed to init SD!#");
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#");
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_static_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1375,7 +1428,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
gui->base_path = (char *)malloc(strlen(sdPath) + 1);
|
||||
strcpy(gui->base_path, sdPath);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
@@ -1438,7 +1491,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
timer = get_tmr_s() - timer;
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
if (res && h_cfg.verification)
|
||||
if (res && n_cfg.verification && !gui->raw_emummc)
|
||||
s_printf(txt_buf, "Time taken: %dm %ds.\n#96FF00 Finished and verified!#", timer / 60, timer % 60);
|
||||
else if (res)
|
||||
s_printf(txt_buf, "Time taken: %dm %ds.\nFinished!", timer / 60, timer % 60);
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
#include "gui.h"
|
||||
#include "fe_emummc_tools.h"
|
||||
#include "../config/config.h"
|
||||
#include "../config/ini.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../storage/mbr_gpt.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/sprintf.h"
|
||||
@@ -36,15 +39,37 @@
|
||||
#define NUM_SECTORS_PER_ITER 8192 // 4MB Cache.
|
||||
#define OUT_FILENAME_SZ 128
|
||||
|
||||
#define MBR_1ST_PART_TYPE_OFF 0x1C2
|
||||
|
||||
extern sdmmc_t sd_sdmmc;
|
||||
extern sdmmc_storage_t sd_storage;
|
||||
extern FATFS sd_fs;
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount(bool deinit);
|
||||
void load_emummc_cfg(emummc_cfg_t *emu_info)
|
||||
{
|
||||
memset(emu_info, 0, sizeof(emummc_cfg_t));
|
||||
|
||||
// Parse emuMMC configuration.
|
||||
LIST_INIT(ini_sections);
|
||||
if (ini_parse(&ini_sections, "emuMMC/emummc.ini", false))
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
if (!strcmp(ini_sec->name, "emummc"))
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||
{
|
||||
if (!strcmp("enabled", kv->key))
|
||||
emu_info->enabled = atoi(kv->val);
|
||||
else if (!strcmp("sector", kv->key))
|
||||
emu_info->sector = strtol(kv->val, NULL, 16);
|
||||
else if (!strcmp("id", kv->key))
|
||||
emu_info->id = strtol(kv->val, NULL, 16);
|
||||
else if (!strcmp("path", kv->key))
|
||||
emu_info->path = kv->val;
|
||||
else if (!strcmp("nintendo_path", kv->key))
|
||||
emu_info->nintendo_path = kv->val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path)
|
||||
{
|
||||
@@ -323,7 +348,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
int base_len = 0;
|
||||
u32 timer = 0;
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
gui->txt_buf = txt_buf;
|
||||
|
||||
s_printf(txt_buf, "");
|
||||
@@ -333,11 +358,11 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
|
||||
if (!sd_mount())
|
||||
{
|
||||
lv_label_set_static_text(gui->label_info, "#FFDD00 Failed to init SD!#");
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#");
|
||||
goto out;
|
||||
}
|
||||
|
||||
lv_label_set_static_text(gui->label_info, "Checking for available free space...");
|
||||
lv_label_set_text(gui->label_info, "Checking for available free space...");
|
||||
manual_system_maintenance(true);
|
||||
|
||||
// Get SD Card free space for Partial Backup.
|
||||
@@ -345,9 +370,9 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_static_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -412,7 +437,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
}
|
||||
|
||||
// Get GP partition size dynamically.
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
// Get GP partition size dynamically.
|
||||
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
|
||||
@@ -596,9 +621,9 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part
|
||||
// Hide the partition.
|
||||
if (active_part == 2)
|
||||
{
|
||||
u8 *mbr = (u8 *)malloc(0x200);
|
||||
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
mbr[MBR_1ST_PART_TYPE_OFF + (0x10 * part_idx)] = 0xE0;
|
||||
mbr->partitions[part_idx].type = 0xE0;
|
||||
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
|
||||
free(mbr);
|
||||
}
|
||||
@@ -611,7 +636,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
|
||||
int res = 0;
|
||||
u32 timer = 0;
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
gui->txt_buf = txt_buf;
|
||||
|
||||
s_printf(txt_buf, "");
|
||||
@@ -621,15 +646,15 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
|
||||
|
||||
if (!sd_mount())
|
||||
{
|
||||
lv_label_set_static_text(gui->label_info, "#FFDD00 Failed to init SD!#");
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#");
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_static_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -650,6 +675,11 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
|
||||
memset(&bootPart, 0, sizeof(bootPart));
|
||||
bootPart.lba_start = 0;
|
||||
bootPart.lba_end = (BOOT_PART_SIZE / NX_EMMC_BLOCKSIZE) - 1;
|
||||
|
||||
// Clear partition start.
|
||||
memset((u8 *)MIXD_BUF_ALIGNED, 0, 0x1000000);
|
||||
sdmmc_storage_write(&sd_storage, sector_start - 0x8000, 0x8000, (u8 *)MIXD_BUF_ALIGNED);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
strcpy(bootPart.name, "BOOT");
|
||||
@@ -682,7 +712,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
|
||||
strcpy(sdPath, gui->base_path);
|
||||
}
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
|
||||
// Get GP partition size dynamically.
|
||||
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
|
||||
|
||||
@@ -20,6 +20,16 @@
|
||||
|
||||
#include "gui.h"
|
||||
|
||||
typedef struct _emummc_cfg_t
|
||||
{
|
||||
int enabled;
|
||||
u32 sector;
|
||||
u16 id;
|
||||
char *path;
|
||||
char *nintendo_path;
|
||||
} emummc_cfg_t;
|
||||
|
||||
void load_emummc_cfg(emummc_cfg_t *emu_info);
|
||||
void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path);
|
||||
void dump_emummc_file(emmc_tool_gui_t *gui);
|
||||
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@ typedef struct _emmc_tool_gui_t
|
||||
lv_obj_t *label_finish;
|
||||
lv_obj_t *bar;
|
||||
lv_style_t *bar_teal_bg;
|
||||
lv_style_t *bar_teal_ind;
|
||||
lv_style_t *bar_white_ind;
|
||||
char *txt_buf;
|
||||
char *base_path;
|
||||
@@ -39,6 +40,7 @@ lv_style_t monospace_text;
|
||||
|
||||
lv_obj_t *payload_list;
|
||||
lv_obj_t *autorcm_btn;
|
||||
lv_obj_t *close_btn;
|
||||
|
||||
lv_img_dsc_t *icon_switch;
|
||||
lv_img_dsc_t *icon_payload;
|
||||
@@ -52,10 +54,15 @@ lv_style_t tabview_btn_pr, tabview_btn_tgl_pr;
|
||||
|
||||
lv_style_t mbox_darken;
|
||||
|
||||
char *text_color;
|
||||
|
||||
void reload_nyx();
|
||||
lv_img_dsc_t *bmp_to_lvimg_obj(const char *path);
|
||||
lv_res_t mbox_action(lv_obj_t * btns, const char * txt);
|
||||
bool nyx_emmc_check_battery_enough();
|
||||
void nyx_window_toggle_buttons(lv_obj_t *win, bool disable);
|
||||
lv_obj_t *nyx_create_standard_window(const char *win_title);
|
||||
lv_obj_t *nyx_create_window_custom_close_btn(const char *win_title, lv_action_t rel_action);
|
||||
void nyx_create_onoff_button(lv_theme_t *th, lv_obj_t *parent, lv_obj_t *btn, const char *btn_name, lv_action_t action, bool transparent);
|
||||
lv_res_t nyx_generic_onoff_toggle(lv_obj_t *btn);
|
||||
void manual_system_maintenance(bool refresh);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2020 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,
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "../mem/heap.h"
|
||||
#include "../sec/se.h"
|
||||
#include "../soc/fuse.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/sprintf.h"
|
||||
#include "../utils/util.h"
|
||||
@@ -37,8 +37,6 @@
|
||||
extern boot_cfg_t b_cfg;
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
typedef struct _emmc_backup_buttons_t
|
||||
@@ -110,20 +108,25 @@ static void _create_window_backup_restore(emmcPartType_t type, const char* win_l
|
||||
lv_obj_align(label_info, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 10);
|
||||
emmc_tool_gui_ctxt.label_info = label_info;
|
||||
|
||||
static lv_style_t bar_teal_bg, bar_white_ind;
|
||||
static lv_style_t bar_teal_bg, bar_teal_ind, bar_white_ind;
|
||||
|
||||
lv_style_copy(&bar_teal_bg, lv_theme_get_current()->bar.bg);
|
||||
bar_teal_bg.body.main_color = LV_COLOR_HEX(0x005a47);
|
||||
bar_teal_bg.body.grad_color = bar_teal_bg.body.main_color;
|
||||
|
||||
lv_style_copy(&bar_teal_ind, lv_theme_get_current()->bar.indic);
|
||||
bar_teal_ind.body.main_color = LV_COLOR_HEX(0x00FFC9);
|
||||
bar_teal_ind.body.grad_color = bar_teal_ind.body.main_color;
|
||||
|
||||
lv_style_copy(&bar_white_ind, lv_theme_get_current()->bar.indic);
|
||||
bar_white_ind.body.main_color = LV_COLOR_HEX(0xF0F0F0);
|
||||
bar_white_ind.body.grad_color = bar_white_ind.body.main_color;
|
||||
|
||||
emmc_tool_gui_ctxt.bar_teal_bg = &bar_teal_bg;
|
||||
emmc_tool_gui_ctxt.bar_teal_ind = &bar_teal_ind;
|
||||
emmc_tool_gui_ctxt.bar_white_ind = &bar_white_ind;
|
||||
|
||||
lv_obj_t * bar = lv_bar_create(h1, NULL);
|
||||
lv_obj_t *bar = lv_bar_create(h1, NULL);
|
||||
lv_obj_set_size(bar, LV_DPI * 38 / 10, LV_DPI / 5);
|
||||
lv_bar_set_range(bar, 0, 100);
|
||||
lv_bar_set_value(bar, 0);
|
||||
@@ -174,6 +177,9 @@ static void _create_window_backup_restore(emmcPartType_t type, const char* win_l
|
||||
|
||||
static lv_res_t _emmc_backup_buttons_decider(lv_obj_t *btn)
|
||||
{
|
||||
if (!nyx_emmc_check_battery_enough())
|
||||
return LV_RES_OK;
|
||||
|
||||
char *win_label = lv_label_get_text(lv_obj_get_child(btn, NULL));
|
||||
|
||||
if (emmc_btn_ctxt.emmc_boot == btn)
|
||||
@@ -240,21 +246,13 @@ static lv_res_t _emmc_backup_buttons_raw_toggle(lv_obj_t *btn)
|
||||
else // Backup/Restore from and to emuMMC.
|
||||
{
|
||||
if (!emmc_btn_ctxt.restore)
|
||||
{
|
||||
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_UPLOAD" SD emuMMC BOOT0 & BOOT1");
|
||||
lv_obj_set_click(emmc_btn_ctxt.emmc_boot, false);
|
||||
lv_btn_set_state(emmc_btn_ctxt.emmc_boot, LV_BTN_STATE_INA);
|
||||
}
|
||||
else
|
||||
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_DOWNLOAD" SD emuMMC BOOT0 & BOOT1");
|
||||
lv_obj_realign(emmc_btn_ctxt.emmc_boot);
|
||||
|
||||
if (!emmc_btn_ctxt.restore)
|
||||
{
|
||||
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_DOWNLOAD" SD emuMMC RAW GPP");
|
||||
lv_obj_set_click(emmc_btn_ctxt.emmc_raw_gpp, false);
|
||||
lv_btn_set_state(emmc_btn_ctxt.emmc_raw_gpp, LV_BTN_STATE_INA);
|
||||
}
|
||||
else
|
||||
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_DOWNLOAD" SD emuMMC RAW GPP");
|
||||
lv_obj_realign(emmc_btn_ctxt.emmc_raw_gpp);
|
||||
|
||||
@@ -18,36 +18,55 @@
|
||||
|
||||
#include "gui.h"
|
||||
#include "fe_emummc_tools.h"
|
||||
#include "gui_tools_partition_manager.h"
|
||||
#include "../../../common/memory_map.h"
|
||||
#include "../config/ini.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/mbr_gpt.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/dirlist.h"
|
||||
#include "../utils/list.h"
|
||||
#include "../utils/sprintf.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
extern sdmmc_t sd_sdmmc;
|
||||
extern sdmmc_storage_t sd_storage;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount(bool deinit);
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
#define MBR_1ST_PART_TYPE_OFF 0x1C2
|
||||
typedef struct _mbr_ctxt_t
|
||||
{
|
||||
u32 available;
|
||||
u32 sector[3];
|
||||
int part_idx;
|
||||
u32 sector_start;
|
||||
} mbr_ctxt_t;
|
||||
|
||||
static int part_idx;
|
||||
static u32 sector_start;
|
||||
static mbr_ctxt_t mbr_ctx;
|
||||
|
||||
static lv_obj_t *emummc_manage_window;
|
||||
static lv_res_t (*emummc_tools)(lv_obj_t *btn);
|
||||
|
||||
static lv_res_t _action_emummc_window_close(lv_obj_t *btn)
|
||||
{
|
||||
lv_win_close_action(btn);
|
||||
lv_obj_del(emummc_manage_window);
|
||||
|
||||
(*emummc_tools)(NULL);
|
||||
|
||||
close_btn = NULL;
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static void _create_window_emummc()
|
||||
{
|
||||
emmc_tool_gui_t emmc_tool_gui_ctxt;
|
||||
|
||||
lv_obj_t *win;
|
||||
if (!part_idx)
|
||||
win = nyx_create_standard_window(SYMBOL_DRIVE" Create SD File emuMMC");
|
||||
if (!mbr_ctx.part_idx)
|
||||
win = nyx_create_window_custom_close_btn(SYMBOL_DRIVE" Create SD File emuMMC", _action_emummc_window_close);
|
||||
else
|
||||
win = nyx_create_standard_window(SYMBOL_DRIVE" Create SD Partition emuMMC");
|
||||
win = nyx_create_window_custom_close_btn(SYMBOL_DRIVE" Create SD Partition emuMMC", _action_emummc_window_close);
|
||||
|
||||
//Disable buttons.
|
||||
nyx_window_toggle_buttons(win, true);
|
||||
@@ -94,7 +113,7 @@ static void _create_window_emummc()
|
||||
lv_obj_align(label_info, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 10);
|
||||
emmc_tool_gui_ctxt.label_info = label_info;
|
||||
|
||||
lv_obj_t * bar = lv_bar_create(h1, NULL);
|
||||
lv_obj_t *bar = lv_bar_create(h1, NULL);
|
||||
lv_obj_set_size(bar, LV_DPI * 38 / 10, LV_DPI / 5);
|
||||
lv_bar_set_range(bar, 0, 100);
|
||||
lv_bar_set_value(bar, 0);
|
||||
@@ -119,28 +138,64 @@ static void _create_window_emummc()
|
||||
lv_obj_align(label_finish, bar, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI * 9 / 20);
|
||||
emmc_tool_gui_ctxt.label_finish = label_finish;
|
||||
|
||||
if (!part_idx)
|
||||
if (!mbr_ctx.part_idx)
|
||||
dump_emummc_file(&emmc_tool_gui_ctxt);
|
||||
else
|
||||
dump_emummc_raw(&emmc_tool_gui_ctxt, part_idx, sector_start);
|
||||
dump_emummc_raw(&emmc_tool_gui_ctxt, mbr_ctx.part_idx, mbr_ctx.sector_start);
|
||||
|
||||
nyx_window_toggle_buttons(win, false);
|
||||
}
|
||||
|
||||
static lv_res_t _create_emummc_raw_format(lv_obj_t * btns, const char * txt)
|
||||
{
|
||||
int btn_idx = lv_btnm_get_pressed(btns);
|
||||
|
||||
// Delete parent mbox.
|
||||
mbox_action(btns, txt);
|
||||
|
||||
// Create partition window.
|
||||
if (!btn_idx)
|
||||
create_window_partition_manager(btns);
|
||||
|
||||
mbr_ctx.part_idx = 0;
|
||||
mbr_ctx.sector_start = 0;
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static lv_res_t _create_emummc_raw_action(lv_obj_t * btns, const char * txt)
|
||||
{
|
||||
int btn_idx = lv_btnm_get_pressed(btns);
|
||||
lv_obj_t *bg = lv_obj_get_parent(lv_obj_get_parent(btns));
|
||||
|
||||
if (!btn_idx)
|
||||
mbr_ctx.sector_start = 0x8000; // Protective offset.
|
||||
|
||||
switch (btn_idx)
|
||||
{
|
||||
case 0:
|
||||
mbr_ctx.part_idx = 1;
|
||||
mbr_ctx.sector_start += mbr_ctx.sector[0];
|
||||
break;
|
||||
case 1:
|
||||
mbr_ctx.part_idx = 2;
|
||||
mbr_ctx.sector_start += mbr_ctx.sector[1];
|
||||
break;
|
||||
case 2:
|
||||
mbr_ctx.part_idx = 3;
|
||||
mbr_ctx.sector_start += mbr_ctx.sector[2];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (btn_idx < 3)
|
||||
{
|
||||
lv_obj_set_style(bg, &lv_style_transp);
|
||||
_create_window_emummc();
|
||||
}
|
||||
|
||||
part_idx = 0;
|
||||
sector_start = 0;
|
||||
mbr_ctx.part_idx = 0;
|
||||
mbr_ctx.sector_start = 0;
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
@@ -153,68 +208,95 @@ static void _create_mbox_emummc_raw()
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char *mbox_btn_map[] = { "\222Continue", "\222Cancel", "" };
|
||||
static const char *mbox_btn_map2[] = { "\211", "OK", "\211", "" };
|
||||
static const char *mbox_btn_format[] = { "\222Continue", "\222Cancel", "" };
|
||||
static char *mbox_btn_parts[] = { "\262Part 1", "\262Part 2", "\262Part 3", "\222Cancel", "" };
|
||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x500);
|
||||
u8 *mbr = (u8 *)malloc(0x200);
|
||||
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
|
||||
|
||||
memset(&mbr_ctx, 0, sizeof(mbr_ctxt_t));
|
||||
|
||||
sd_mount();
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
sd_unmount(false);
|
||||
memcpy(mbr, mbr + 0x1BE, 0x40);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
u32 curr_part_size = *(u32 *)&mbr[0x0C + (0x10 * i)];
|
||||
sector_start = *(u32 *)&mbr[0x08 + (0x10 * i)];
|
||||
u8 type = mbr[0x04 + (0x10 * i)];
|
||||
if ((curr_part_size >= (storage.sec_cnt + 0xC000)) && sector_start && type != 0x83) //! TODO: For now it skips linux partitions.
|
||||
{
|
||||
part_idx = i;
|
||||
sector_start += 0x8000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
u32 emmc_size_safe = storage.sec_cnt + 0xC000; // eMMC GPP size + BOOT0/1.
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
|
||||
if (part_idx)
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
u32 part_size = mbr->partitions[i].size_sct;
|
||||
u32 part_start = mbr->partitions[i].start_sct;
|
||||
u8 part_type = mbr->partitions[i].type;
|
||||
bool valid_part = (part_type != 0x83) && (part_type != 0xEE); // Skip Linux and GPT (Android) partitions.
|
||||
|
||||
if ((part_size >= emmc_size_safe) && part_start > 0x8000 && valid_part)
|
||||
{
|
||||
mbr_ctx.available |= (1 << (i - 1));
|
||||
mbr_ctx.sector[i - 1] = part_start;
|
||||
}
|
||||
}
|
||||
|
||||
if (mbr_ctx.available)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found applicable partition: [Part %d]!#\n"
|
||||
"#FF8000 Do you want to continue?#\n\n", part_idx);
|
||||
"#C7EA46 Found applicable partition(s)!#\n"
|
||||
"#FF8000 Choose a partition to continue:#\n\n");
|
||||
}
|
||||
else
|
||||
s_printf(txt_buf, "Failed to find applicable partition!\n\n");
|
||||
s_printf(txt_buf, "#FFDD00 Failed to find applicable partition!#\n\n");
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf),
|
||||
"Partition table:\n"
|
||||
"Part 0: Type: %02x, Start: %08x, Size: %08x\n"
|
||||
"Part 1: Type: %02x, Start: %08x, Size: %08x\n"
|
||||
"Part 2: Type: %02x, Start: %08x, Size: %08x\n"
|
||||
"Part 3: Type: %02x, Start: %08x, Size: %08x\n",
|
||||
mbr[0x04], *(u32 *)&mbr[0x08], *(u32 *)&mbr[0x0C],
|
||||
mbr[0x14], *(u32 *)&mbr[0x18], *(u32 *)&mbr[0x1C],
|
||||
mbr[0x24], *(u32 *)&mbr[0x28], *(u32 *)&mbr[0x2C],
|
||||
mbr[0x34], *(u32 *)&mbr[0x38], *(u32 *)&mbr[0x3C]);
|
||||
"#C0C0C0 Part 0: Type: %02x, Start: %08x, Size: %08x#\n"
|
||||
"#%s Part 1: Type: %02x, Start: %08x, Size: %08x#\n"
|
||||
"#%s Part 2: Type: %02x, Start: %08x, Size: %08x#\n"
|
||||
"#%s Part 3: Type: %02x, Start: %08x, Size: %08x#\n",
|
||||
mbr->partitions[0].type, mbr->partitions[0].start_sct, mbr->partitions[0].size_sct,
|
||||
(mbr_ctx.available & 1) ? "C7EA46" : "C0C0C0",
|
||||
mbr->partitions[1].type, mbr->partitions[1].start_sct, mbr->partitions[1].size_sct,
|
||||
(mbr_ctx.available & 2) ? "C7EA46" : "C0C0C0",
|
||||
mbr->partitions[2].type, mbr->partitions[2].start_sct, mbr->partitions[2].size_sct,
|
||||
(mbr_ctx.available & 4) ? "C7EA46" : "C0C0C0",
|
||||
mbr->partitions[3].type, mbr->partitions[3].start_sct, mbr->partitions[3].size_sct);
|
||||
|
||||
if (!mbr_ctx.available)
|
||||
s_printf(txt_buf + strlen(txt_buf),
|
||||
"\n#FF8000 Do you want to partition your SD card?#\n"
|
||||
"#FF8000 (You will be asked on how to proceed)#");
|
||||
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
free(txt_buf);
|
||||
free(mbr);
|
||||
|
||||
if (part_idx)
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_raw_action);
|
||||
if (mbr_ctx.available)
|
||||
{
|
||||
// Check available partitions and enable the corresponding buttons.
|
||||
if (mbr_ctx.available & 1)
|
||||
mbox_btn_parts[0][0] = '\222';
|
||||
else
|
||||
mbox_btn_parts[0][0] = '\262';
|
||||
if (mbr_ctx.available & 2)
|
||||
mbox_btn_parts[1][0] = '\222';
|
||||
else
|
||||
mbox_btn_parts[1][0] = '\262';
|
||||
if (mbr_ctx.available & 4)
|
||||
mbox_btn_parts[2][0] = '\222';
|
||||
else
|
||||
mbox_btn_parts[2][0] = '\262';
|
||||
|
||||
lv_mbox_add_btns(mbox, (const char **)mbox_btn_parts, _create_emummc_raw_action);
|
||||
}
|
||||
else
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map2, mbox_action);
|
||||
lv_mbox_add_btns(mbox, mbox_btn_format, _create_emummc_raw_format);
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
@@ -225,8 +307,8 @@ static lv_res_t _create_emummc_action(lv_obj_t * btns, const char * txt)
|
||||
int btn_idx = lv_btnm_get_pressed(btns);
|
||||
lv_obj_t *bg = lv_obj_get_parent(lv_obj_get_parent(btns));
|
||||
|
||||
part_idx = 0;
|
||||
sector_start = 0;
|
||||
mbr_ctx.part_idx = 0;
|
||||
mbr_ctx.sector_start = 0;
|
||||
|
||||
switch (btn_idx)
|
||||
{
|
||||
@@ -236,7 +318,6 @@ static lv_res_t _create_emummc_action(lv_obj_t * btns, const char * txt)
|
||||
break;
|
||||
case 1:
|
||||
_create_mbox_emummc_raw();
|
||||
// if available. have max 3 buttons. if selected and used, ask to use the backup tool.
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -247,6 +328,9 @@ static lv_res_t _create_emummc_action(lv_obj_t * btns, const char * txt)
|
||||
|
||||
static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn)
|
||||
{
|
||||
if (!nyx_emmc_check_battery_enough())
|
||||
return LV_RES_OK;
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
@@ -272,16 +356,16 @@ static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn)
|
||||
|
||||
static void _change_raw_emummc_part_type()
|
||||
{
|
||||
u8 *mbr = (u8 *)malloc(0x200);
|
||||
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
mbr[MBR_1ST_PART_TYPE_OFF + (0x10 * part_idx)] = 0xE0;
|
||||
mbr->partitions[mbr_ctx.part_idx].type = 0xE0;
|
||||
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
|
||||
free(mbr);
|
||||
}
|
||||
|
||||
static void _migrate_sd_raw_based()
|
||||
{
|
||||
sector_start = 2;
|
||||
mbr_ctx.sector_start = 2;
|
||||
|
||||
sd_mount();
|
||||
f_mkdir("emuMMC");
|
||||
@@ -290,17 +374,17 @@ static void _migrate_sd_raw_based()
|
||||
f_rename("Emutendo", "emuMMC/ER00/Nintendo");
|
||||
FIL fp;
|
||||
f_open(&fp, "emuMMC/ER00/raw_based", FA_CREATE_ALWAYS | FA_WRITE);
|
||||
f_write(&fp, §or_start, 4, NULL);
|
||||
f_write(&fp, &mbr_ctx.sector_start, 4, NULL);
|
||||
f_close(&fp);
|
||||
|
||||
save_emummc_cfg(1, sector_start, "emuMMC/ER00");
|
||||
save_emummc_cfg(1, mbr_ctx.sector_start, "emuMMC/ER00");
|
||||
sd_unmount(false);
|
||||
}
|
||||
|
||||
static void _migrate_sd_raw_emummc_based()
|
||||
{
|
||||
char *tmp = (char *)malloc(0x80);
|
||||
s_printf(tmp, "emuMMC/RAW%d", part_idx);
|
||||
s_printf(tmp, "emuMMC/RAW%d", mbr_ctx.part_idx);
|
||||
|
||||
sd_mount();
|
||||
f_mkdir("emuMMC");
|
||||
@@ -310,15 +394,15 @@ static void _migrate_sd_raw_emummc_based()
|
||||
FIL fp;
|
||||
if (!f_open(&fp, tmp, FA_CREATE_ALWAYS | FA_WRITE))
|
||||
{
|
||||
f_write(&fp, §or_start, 4, NULL);
|
||||
f_write(&fp, &mbr_ctx.sector_start, 4, NULL);
|
||||
f_close(&fp);
|
||||
}
|
||||
|
||||
s_printf(tmp, "emuMMC/RAW%d", part_idx);
|
||||
s_printf(tmp, "emuMMC/RAW%d", mbr_ctx.part_idx);
|
||||
|
||||
_change_raw_emummc_part_type();
|
||||
|
||||
save_emummc_cfg(part_idx, sector_start, tmp);
|
||||
save_emummc_cfg(mbr_ctx.part_idx, mbr_ctx.sector_start, tmp);
|
||||
|
||||
free(tmp);
|
||||
|
||||
@@ -423,8 +507,8 @@ static lv_res_t _create_emummc_mig1_action(lv_obj_t * btns, const char * txt)
|
||||
break;
|
||||
}
|
||||
|
||||
part_idx = 0;
|
||||
sector_start = 0;
|
||||
mbr_ctx.part_idx = 0;
|
||||
mbr_ctx.sector_start = 0;
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
@@ -440,8 +524,8 @@ static lv_res_t _create_emummc_mig0_action(lv_obj_t * btns, const char * txt)
|
||||
break;
|
||||
}
|
||||
|
||||
part_idx = 0;
|
||||
sector_start = 0;
|
||||
mbr_ctx.part_idx = 0;
|
||||
mbr_ctx.sector_start = 0;
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
@@ -457,8 +541,8 @@ static lv_res_t _create_emummc_mig2_action(lv_obj_t * btns, const char * txt)
|
||||
break;
|
||||
}
|
||||
|
||||
part_idx = 0;
|
||||
sector_start = 0;
|
||||
mbr_ctx.part_idx = 0;
|
||||
mbr_ctx.sector_start = 0;
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
@@ -474,8 +558,8 @@ static lv_res_t _create_emummc_mig3_action(lv_obj_t * btns, const char * txt)
|
||||
break;
|
||||
}
|
||||
|
||||
part_idx = 0;
|
||||
sector_start = 0;
|
||||
mbr_ctx.part_idx = 0;
|
||||
mbr_ctx.sector_start = 0;
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
@@ -491,8 +575,8 @@ static lv_res_t _create_emummc_mig4_action(lv_obj_t * btns, const char * txt)
|
||||
break;
|
||||
}
|
||||
|
||||
part_idx = 0;
|
||||
sector_start = 0;
|
||||
mbr_ctx.part_idx = 0;
|
||||
mbr_ctx.sector_start = 0;
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
@@ -513,7 +597,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x500);
|
||||
u8 *mbr = (u8 *)malloc(0x200);
|
||||
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
|
||||
u8 *efi_part = (u8 *)malloc(0x200);
|
||||
|
||||
sd_mount();
|
||||
@@ -523,35 +607,35 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
bool backup = false;
|
||||
bool emummc = false;
|
||||
bool file_based = false;
|
||||
bool em = false;
|
||||
sector_start = 0;
|
||||
part_idx = 0;
|
||||
mbr_ctx.sector_start = 0;
|
||||
mbr_ctx.part_idx = 0;
|
||||
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
sector_start = *(u32 *)&mbr[0x08 + (0x10 * i)];
|
||||
if (sector_start)
|
||||
mbr_ctx.sector_start = mbr->partitions[i].start_sct;
|
||||
if (mbr_ctx.sector_start)
|
||||
{
|
||||
sdmmc_storage_read(&sd_storage, sector_start + 0xC001, 1, efi_part);
|
||||
sdmmc_storage_read(&sd_storage, mbr_ctx.sector_start + 0xC001, 1, efi_part);
|
||||
if (!memcmp(efi_part, "EFI PART", 8))
|
||||
{
|
||||
sector_start += 0x8000;
|
||||
mbr_ctx.sector_start += 0x8000;
|
||||
emummc = true;
|
||||
part_idx = i;
|
||||
mbr_ctx.part_idx = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sdmmc_storage_read(&sd_storage, sector_start + 0x4001, 1, efi_part);
|
||||
sdmmc_storage_read(&sd_storage, mbr_ctx.sector_start + 0x4001, 1, efi_part);
|
||||
if (!memcmp(efi_part, "EFI PART", 8))
|
||||
{
|
||||
emummc = true;
|
||||
part_idx = i;
|
||||
mbr_ctx.part_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -560,7 +644,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
|
||||
//! TODO: What about unallocated
|
||||
|
||||
if (!part_idx)
|
||||
if (!mbr_ctx.part_idx)
|
||||
{
|
||||
sdmmc_storage_read(&sd_storage, 0x4003, 1, efi_part);
|
||||
if (!memcmp(efi_part, "EFI PART", 8))
|
||||
@@ -658,10 +742,6 @@ typedef struct _emummc_images_t
|
||||
|
||||
static emummc_images_t *emummc_img;
|
||||
|
||||
static lv_obj_t *emummc_manage_window;
|
||||
|
||||
static lv_res_t (*emummc_tools)(lv_obj_t *btn);
|
||||
|
||||
static lv_res_t _save_emummc_cfg_mbox_action(lv_obj_t *btns, const char *txt)
|
||||
{
|
||||
free(emummc_img->dirlist);
|
||||
@@ -737,7 +817,7 @@ static lv_res_t _save_file_emummc_cfg_action(lv_obj_t *btn)
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static lv_res_t _create_change_emummc_window()
|
||||
static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller)
|
||||
{
|
||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_SETTINGS" Change emuMMC");
|
||||
lv_win_add_btn(win, NULL, SYMBOL_POWER" Disable", _save_disable_emummc_cfg_action);
|
||||
@@ -747,19 +827,18 @@ static lv_res_t _create_change_emummc_window()
|
||||
emummc_img = malloc(sizeof(emummc_images_t));
|
||||
emummc_img->win = win;
|
||||
|
||||
u8 *mbr = (u8 *)malloc(0x200);
|
||||
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
|
||||
char *path = malloc(256);
|
||||
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
|
||||
memcpy(mbr, mbr + 0x1BE, 0x40);
|
||||
memset(emummc_img->part_path, 0, 3 * 128);
|
||||
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
emummc_img->part_sector[i - 1] = *(u32 *)&mbr[0x08 + (0x10 * i)];
|
||||
emummc_img->part_end[i - 1] = emummc_img->part_sector[i - 1] + *(u32 *)&mbr[0x0C + (0x10 * i)] - 1;
|
||||
emummc_img->part_type[i - 1] = mbr[0x04 + (0x10 * i)];
|
||||
emummc_img->part_sector[i - 1] = mbr->partitions[i].start_sct;
|
||||
emummc_img->part_end[i - 1] = emummc_img->part_sector[i - 1] + mbr->partitions[i].size_sct - 1;
|
||||
emummc_img->part_type[i - 1] = mbr->partitions[i].type;
|
||||
}
|
||||
free(mbr);
|
||||
|
||||
@@ -965,50 +1044,10 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn)
|
||||
|
||||
emummc_tools = (void *)create_win_emummc_tools;
|
||||
|
||||
typedef struct _emummc_cfg_t
|
||||
{
|
||||
int enabled;
|
||||
u32 sector;
|
||||
u16 id;
|
||||
char *path;
|
||||
char *nintendo_path;
|
||||
} emummc_cfg_t;
|
||||
|
||||
emummc_cfg_t emu_info;
|
||||
|
||||
sd_mount();
|
||||
|
||||
emu_info.enabled = 0;
|
||||
emu_info.sector = 0;
|
||||
emu_info.id = 0;
|
||||
emu_info.path = NULL;
|
||||
emu_info.nintendo_path = NULL;
|
||||
|
||||
//! TODO: Always update that info when something was changed.
|
||||
// Parse emuMMC configuration.
|
||||
LIST_INIT(ini_sections);
|
||||
if (ini_parse(&ini_sections, "emuMMC/emummc.ini", false))
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||
{
|
||||
if (!strcmp(ini_sec->name, "emummc"))
|
||||
{
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||
{
|
||||
if (!strcmp("enabled", kv->key))
|
||||
emu_info.enabled = atoi(kv->val);
|
||||
else if (!strcmp("sector", kv->key))
|
||||
emu_info.sector = strtol(kv->val, NULL, 16);
|
||||
else if (!strcmp("id", kv->key))
|
||||
emu_info.id = strtol(kv->val, NULL, 16);
|
||||
else if (!strcmp("path", kv->key))
|
||||
emu_info.path = kv->val;
|
||||
else if (!strcmp("nintendo_path", kv->key))
|
||||
emu_info.nintendo_path = kv->val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
emummc_cfg_t emu_info;
|
||||
load_emummc_cfg(&emu_info);
|
||||
|
||||
sd_unmount(false);
|
||||
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
*/
|
||||
|
||||
#include "gui.h"
|
||||
#include "../gfx/di.h"
|
||||
#include "../hos/hos.h"
|
||||
#include "../hos/pkg1.h"
|
||||
#include "../libs/fatfs/ff.h"
|
||||
#include "../input/touch.h"
|
||||
#include "../mem/emc.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../mem/sdram.h"
|
||||
#include "../power/bq24193.h"
|
||||
#include "../power/max17050.h"
|
||||
#include "../sec/tsec.h"
|
||||
@@ -31,18 +35,16 @@
|
||||
#include "../soc/t210.h"
|
||||
#include "../storage/mmc.h"
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../storage/sdmmc.h"
|
||||
#include "../utils/btn.h"
|
||||
#include "../utils/sprintf.h"
|
||||
#include "../utils/util.h"
|
||||
|
||||
#define SECTORS_TO_MIB_COEFF 11
|
||||
|
||||
extern sdmmc_storage_t sd_storage;
|
||||
extern FATFS sd_fs;
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount(bool deinit);
|
||||
extern int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
extern void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage);
|
||||
|
||||
static lv_res_t _create_window_dump_done(int error, char *dump_filenames)
|
||||
@@ -156,7 +158,6 @@ static lv_res_t _bootrom_dump_window_action(lv_obj_t * btn)
|
||||
}
|
||||
_create_window_dump_done(error, "evp_thunks.bin, bootrom_patched.bin, bootrom_unpatched.bin");
|
||||
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
@@ -225,7 +226,7 @@ static lv_res_t _tsec_keys_dump_window_action(lv_obj_t * btn)
|
||||
|
||||
static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
{
|
||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_CHIP" Cached fuses Info");
|
||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_CHIP" HW & Cached Fuses Info");
|
||||
lv_win_add_btn(win, NULL, SYMBOL_DOWNLOAD" Dump fuses", _fuse_dump_window_action);
|
||||
|
||||
lv_obj_t *desc = lv_cont_create(win, NULL);
|
||||
@@ -234,7 +235,7 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
|
||||
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_recolor(lb_desc, true);
|
||||
lv_ta_set_style(lb_desc, LV_TA_STYLE_BG, &monospace_text);
|
||||
lv_label_set_style(lb_desc, &monospace_text);
|
||||
|
||||
lv_label_set_static_text(lb_desc,
|
||||
"#00DDFF Detailed Info:#\n"
|
||||
@@ -262,7 +263,8 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
"LOT Code 1:\n"
|
||||
"Wafer ID:\n"
|
||||
"X Coordinate:\n"
|
||||
"Y Coordinate:"
|
||||
"Y Coordinate:\n"
|
||||
"#FF8000 Chip ID Revision:#"
|
||||
);
|
||||
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
|
||||
|
||||
@@ -271,7 +273,7 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
|
||||
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
|
||||
// Decode fuses.
|
||||
u8 burntFuses7 = 0;
|
||||
@@ -317,11 +319,13 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
lot_code0 <<= 6;
|
||||
}
|
||||
|
||||
u32 chip_id = APB_MISC(APB_MISC_GP_HIDREV);
|
||||
// Parse fuses and display them.
|
||||
s_printf(txt_buf,
|
||||
"\n%X - %s - %s\n%d - %s\n%d - %d\n%08X%08X%08X%08X\n%08X\n"
|
||||
"%s\n%d.%02d (0x%X)\n%d.%02d (0x%X)\n%d\n%d\n%d\n%d\n%d\n0x%X\n%d\n%d\n%d\n%d\n"
|
||||
"%d\n%d\n%d (0x%X)\n%d\n%d\n%d\n%d",
|
||||
"%d\n%d\n%d (0x%X)\n%d\n%d\n%d\n%d\n"
|
||||
"ID: %02X, Major: A0%d, Minor: %d",
|
||||
FUSE(FUSE_SKU_INFO), odm4 & 0x10000 ? "Mariko" : "Erista", (fuse_read_odm(4) & 3) ? "Dev" : "Retail",
|
||||
dram_id, dram_man, burntFuses7, burntFuses6,
|
||||
byte_swap_32(FUSE(FUSE_PRIVATE_KEY0)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY1)),
|
||||
@@ -335,12 +339,11 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
FUSE(FUSE_SOC_SPEEDO_0_CALIB), FUSE(FUSE_SOC_SPEEDO_1_CALIB), FUSE(FUSE_SOC_SPEEDO_2_CALIB),
|
||||
FUSE(FUSE_CPU_IDDQ_CALIB), FUSE(FUSE_SOC_IDDQ_CALIB), FUSE(FUSE_GPU_IDDQ_CALIB),
|
||||
FUSE(FUSE_OPT_VENDOR_CODE), FUSE(FUSE_OPT_FAB_CODE), lot_bin, FUSE(FUSE_OPT_LOT_CODE_0),
|
||||
FUSE(FUSE_OPT_LOT_CODE_1), FUSE(FUSE_OPT_WAFER_ID), FUSE(FUSE_OPT_X_COORDINATE), FUSE(FUSE_OPT_Y_COORDINATE));
|
||||
FUSE(FUSE_OPT_LOT_CODE_1), FUSE(FUSE_OPT_WAFER_ID), FUSE(FUSE_OPT_X_COORDINATE), FUSE(FUSE_OPT_Y_COORDINATE),
|
||||
(chip_id >> 8) & 0xFF, (chip_id >> 4) & 0xF, (chip_id >> 16) & 0xF);
|
||||
|
||||
lv_label_set_text(lb_val, txt_buf);
|
||||
|
||||
free(txt_buf);
|
||||
|
||||
lv_obj_set_width(lb_val, lv_obj_get_width(val));
|
||||
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||
|
||||
@@ -351,15 +354,169 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
||||
lv_label_set_long_mode(lb_desc2, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_recolor(lb_desc2, true);
|
||||
|
||||
// DRAM info.
|
||||
emc_mr_data_t ram_vendor = sdram_read_mrx(MR5_MAN_ID);
|
||||
emc_mr_data_t ram_rev0 = sdram_read_mrx(MR6_REV_ID1);
|
||||
emc_mr_data_t ram_rev1 = sdram_read_mrx(MR7_REV_ID2);
|
||||
emc_mr_data_t ram_density = sdram_read_mrx(MR8_DENSITY);
|
||||
s_printf(txt_buf, "#00DDFF LPDDR4 SDRAM ##FF8000 Slot 0 | Slot 1:#\n#FF8000 Vendor:# ");
|
||||
switch (ram_vendor.dev0_ch0)
|
||||
{
|
||||
case 1:
|
||||
s_printf(txt_buf + strlen(txt_buf), "Samsung");
|
||||
break;
|
||||
case 6:
|
||||
s_printf(txt_buf + strlen(txt_buf), "Hynix");
|
||||
break;
|
||||
case 255:
|
||||
s_printf(txt_buf + strlen(txt_buf), "Micron");
|
||||
break;
|
||||
default:
|
||||
s_printf(txt_buf + strlen(txt_buf), "Unknown");
|
||||
break;
|
||||
}
|
||||
s_printf(txt_buf + strlen(txt_buf), " (%d) #FF8000 |# ", ram_vendor.dev0_ch0);
|
||||
switch (ram_vendor.dev1_ch0)
|
||||
{
|
||||
case 1:
|
||||
s_printf(txt_buf + strlen(txt_buf), "Samsung");
|
||||
break;
|
||||
case 6:
|
||||
s_printf(txt_buf + strlen(txt_buf), "Hynix");
|
||||
break;
|
||||
case 255:
|
||||
s_printf(txt_buf + strlen(txt_buf), "Micron");
|
||||
break;
|
||||
default:
|
||||
s_printf(txt_buf + strlen(txt_buf), "Unknown");
|
||||
break;
|
||||
}
|
||||
s_printf(txt_buf + strlen(txt_buf), " (%d)\n#FF8000 Rev ID:# %04X #FF8000 |# %04X\n#FF8000 Density:# ",
|
||||
ram_vendor.dev1_ch0, (ram_rev0.dev0_ch0 << 8) | ram_rev1.dev0_ch0, (ram_rev0.dev1_ch0 << 8) | ram_rev1.dev1_ch0);
|
||||
switch ((ram_density.dev0_ch0 & 0x3C) >> 2)
|
||||
{
|
||||
case 2:
|
||||
s_printf(txt_buf + strlen(txt_buf), "4 x 512MB");
|
||||
break;
|
||||
case 3:
|
||||
s_printf(txt_buf + strlen(txt_buf), "4 x 768MB");
|
||||
break;
|
||||
case 4:
|
||||
s_printf(txt_buf + strlen(txt_buf), "4 x 1GB");
|
||||
break;
|
||||
default:
|
||||
s_printf(txt_buf + strlen(txt_buf), "4 x Unk");
|
||||
break;
|
||||
}
|
||||
s_printf(txt_buf + strlen(txt_buf), " (%d) #FF8000 |# ", (ram_density.dev0_ch0 & 0x3C) >> 2);
|
||||
switch ((ram_density.dev1_ch0 & 0x3C) >> 2)
|
||||
{
|
||||
case 2:
|
||||
s_printf(txt_buf + strlen(txt_buf), "4 x 512MB");
|
||||
break;
|
||||
case 3:
|
||||
s_printf(txt_buf + strlen(txt_buf), "4 x 768MB");
|
||||
break;
|
||||
case 4:
|
||||
s_printf(txt_buf + strlen(txt_buf), "4 x 1GB");
|
||||
break;
|
||||
default:
|
||||
s_printf(txt_buf + strlen(txt_buf), "2 x Unk");
|
||||
break;
|
||||
}
|
||||
s_printf(txt_buf + strlen(txt_buf), " (%d)\n\n", (ram_density.dev1_ch0 & 0x3C) >> 2);
|
||||
|
||||
// Display info.
|
||||
u32 display_id = ((nyx_str->info.disp_id >> 8) & 0xFF00) | (nyx_str->info.disp_id & 0xFF);
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "#00DDFF Display Panel:#\n#FF8000 Model:# ");
|
||||
|
||||
switch (display_id)
|
||||
{
|
||||
case PANEL_JDI_LAM062M109A:
|
||||
s_printf(txt_buf + strlen(txt_buf), "JDI LAM062M109A");
|
||||
break;
|
||||
case PANEL_JDI_LPM062M326A:
|
||||
s_printf(txt_buf + strlen(txt_buf), "JDI LPM062M326A");
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
s_printf(txt_buf + strlen(txt_buf), "InnoLux P062CCA-AZ1");
|
||||
break;
|
||||
case PANEL_AUO_A062TAN01:
|
||||
s_printf(txt_buf + strlen(txt_buf), "AUO A062TAN01");
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ2:
|
||||
s_printf(txt_buf + strlen(txt_buf), "InnoLux P062CCA-AZ2");
|
||||
break;
|
||||
case PANEL_AUO_A062TAN02:
|
||||
s_printf(txt_buf + strlen(txt_buf), "AUO A062TAN02");
|
||||
break;
|
||||
default:
|
||||
switch (display_id & 0xFF)
|
||||
{
|
||||
case PANEL_JDI_LPM062M:
|
||||
s_printf(txt_buf + strlen(txt_buf), "JDI ");
|
||||
break;
|
||||
case (PANEL_INL_P062CCA_AZ1 & 0xFF):
|
||||
s_printf(txt_buf + strlen(txt_buf), "InnoLux ");
|
||||
break;
|
||||
case (PANEL_AUO_A062TAN01 & 0xFF):
|
||||
s_printf(txt_buf + strlen(txt_buf), "AUO ");
|
||||
break;
|
||||
}
|
||||
s_printf(txt_buf + strlen(txt_buf), "Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 ID:# [%02X] %02X [%02X]",
|
||||
nyx_str->info.disp_id & 0xFF, (nyx_str->info.disp_id >> 8) & 0xFF, (nyx_str->info.disp_id >> 16) & 0xFF);
|
||||
|
||||
touch_fw_info_t touch_fw;
|
||||
|
||||
if (!touch_get_fw_info(&touch_fw))
|
||||
{
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n\n#00DDFF Touch Panel:#\n#FF8000 Model:# ");
|
||||
switch (touch_fw.fw_id)
|
||||
{
|
||||
case 0x100100:
|
||||
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD 1601");
|
||||
break;
|
||||
case 0x00120100:
|
||||
case 0x32000001:
|
||||
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD 1801");
|
||||
break;
|
||||
case 0x001A0300:
|
||||
case 0x32000102:
|
||||
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD 2602");
|
||||
break;
|
||||
case 0x00290100:
|
||||
case 0x32000302:
|
||||
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD 3801");
|
||||
break;
|
||||
case 0x31051820:
|
||||
case 0x32000402:
|
||||
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD XXXX");
|
||||
break;
|
||||
default:
|
||||
s_printf(txt_buf + strlen(txt_buf), "Unknown");
|
||||
}
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 ID:# %X\n#FF8000 FTB ver:# %04X\n#FF8000 FW rev:# %04X",
|
||||
touch_fw.fw_id, touch_fw.ftb_ver, touch_fw.fw_rev);
|
||||
}
|
||||
|
||||
// Check if patched unit.
|
||||
if (!fuse_check_patched_rcm())
|
||||
lv_label_set_static_text(lb_desc2, "#96FF00 Your unit is exploitable#\n#96FF00 to the RCM bug!#");
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n\n#96FF00 Your unit is exploitable#\n#96FF00 to the RCM bug!#");
|
||||
else
|
||||
lv_label_set_static_text(lb_desc2, "#FF8000 Your unit is patched#\n#FF8000 to the RCM bug!#");
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n\n#FF8000 Your unit is patched#\n#FF8000 to the RCM bug!#");
|
||||
|
||||
lv_label_set_text(lb_desc2, txt_buf);
|
||||
|
||||
free(txt_buf);
|
||||
|
||||
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
|
||||
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
|
||||
lv_label_set_align(lb_desc2, LV_LABEL_ALIGN_CENTER);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
@@ -392,7 +549,7 @@ static lv_res_t _create_window_bootrom_info_status(lv_obj_t *btn)
|
||||
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
|
||||
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_recolor(lb_desc, true);
|
||||
lv_ta_set_style(lb_desc, LV_TA_STYLE_BG, &monospace_text);
|
||||
lv_label_set_style(lb_desc, &monospace_text);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
ipatches_txt = txt_buf;
|
||||
@@ -431,13 +588,13 @@ static lv_res_t _create_window_tsec_keys_status(lv_obj_t *btn)
|
||||
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
|
||||
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_recolor(lb_desc, true);
|
||||
lv_ta_set_style(lb_desc, LV_TA_STYLE_BG, &monospace_text);
|
||||
lv_label_set_style(lb_desc, &monospace_text);
|
||||
|
||||
// Read package1.
|
||||
char *build_date = malloc(32);
|
||||
u8 *pkg1 = (u8 *)malloc(0x40000);
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4);
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1, build_date);
|
||||
@@ -462,9 +619,9 @@ static lv_res_t _create_window_tsec_keys_status(lv_obj_t *btn)
|
||||
lv_obj_set_size(val, LV_HOR_RES / 11 * 3, LV_VER_RES - (LV_DPI * 11 / 6));
|
||||
|
||||
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
|
||||
lv_ta_set_style(lb_val, LV_TA_STYLE_BG, &monospace_text);
|
||||
lv_label_set_style(lb_val, &monospace_text);
|
||||
|
||||
lv_label_set_static_text(lb_val, "Please wait...");
|
||||
lv_label_set_text(lb_val, "Please wait...");
|
||||
lv_obj_set_width(lb_val, lv_obj_get_width(val));
|
||||
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||
manual_system_maintenance(true);
|
||||
@@ -542,10 +699,147 @@ out:
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
{
|
||||
sdmmc_t emmc_sdmmc;
|
||||
sdmmc_storage_t emmc_storage;
|
||||
sdmmc_storage_t *storage;
|
||||
|
||||
lv_style_t *darken;
|
||||
darken = (lv_style_t *)malloc(sizeof(lv_style_t));
|
||||
lv_style_copy(darken, &lv_style_plain);
|
||||
darken->body.main_color = LV_COLOR_BLACK;
|
||||
darken->body.grad_color = darken->body.main_color;
|
||||
darken->body.opa = LV_OPA_30;
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char * mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 7 * 5);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
|
||||
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[3 x %s raw reads. Cancel: VOL- & VOL+]\n",
|
||||
sd_bench ? "SD Card" : "eMMC", sd_bench ? "2GB" : "8GB");
|
||||
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
|
||||
lv_obj_t * bar = lv_bar_create(mbox, NULL);
|
||||
lv_obj_set_size(bar, LV_DPI * 2, LV_DPI / 5);
|
||||
lv_bar_set_range(bar, 0, 100);
|
||||
lv_bar_set_value(bar, 0);
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
int res = 0;
|
||||
|
||||
if (sd_bench)
|
||||
{
|
||||
storage = &sd_storage;
|
||||
res = !sd_mount();
|
||||
}
|
||||
else
|
||||
{
|
||||
storage = &emmc_storage;
|
||||
res = !sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
if (!res)
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
}
|
||||
|
||||
if (res)
|
||||
lv_mbox_set_text(mbox, "#FFDD00 Failed to init Storage!#");
|
||||
else
|
||||
{
|
||||
u32 iters = 3;
|
||||
u32 sector_num = 0x8000;
|
||||
u32 data_scts = sd_bench ? 0x400000 : 0x1000000; // SD 2GB or eMMC 8GB.
|
||||
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, sector_num);
|
||||
if (storage->sec_cnt < 0xC00000)
|
||||
iters -= 2; // 4GB card.
|
||||
|
||||
for (u32 iter_curr = 0; iter_curr < iters; iter_curr++)
|
||||
{
|
||||
u32 pct = 0;
|
||||
u32 prevPct = 200;
|
||||
u32 lba_curr = 0;
|
||||
u32 sector = offset_chunk_start * iter_curr;
|
||||
u32 data_remaining = data_scts;
|
||||
|
||||
u32 timer = get_tmr_ms();
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "\n");
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
|
||||
while (data_remaining)
|
||||
{
|
||||
// Read 16MB chunks.
|
||||
sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
manual_system_maintenance(false);
|
||||
data_remaining -= sector_num;
|
||||
lba_curr += sector_num;
|
||||
|
||||
pct = (lba_curr * 100) / data_scts;
|
||||
if (pct != prevPct)
|
||||
{
|
||||
lv_bar_set_value(bar, pct);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
prevPct = pct;
|
||||
|
||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
break;
|
||||
}
|
||||
}
|
||||
timer = get_tmr_ms() - timer;
|
||||
timer -= sd_bench ? 175 : 185; // Compensate 175ms/185ms for maintenance/drawing/calc ops.
|
||||
|
||||
lv_bar_set_value(bar, 100);
|
||||
u32 rate_1k = (sd_bench ? (2048 * 1000 * 1000) : (u64)((u64)8192 * 1000 * 1000)) / timer;
|
||||
s_printf(txt_buf + strlen(txt_buf),
|
||||
"#C7EA46 %d#: Offset: #C7EA46 %08X#, Time: #C7EA46 %d.%02ds#, Rate: #C7EA46 %d.%02d MB/s#",
|
||||
iter_curr, sector, timer / 1000, (timer % 1000) / 10, rate_1k / 1000, (rate_1k % 1000) / 10);
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
manual_system_maintenance(true);
|
||||
}
|
||||
|
||||
lv_obj_del(bar);
|
||||
|
||||
if (sd_bench)
|
||||
sd_unmount(false);
|
||||
else
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
}
|
||||
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _create_mbox_emmc_bench(lv_obj_t * btn)
|
||||
{
|
||||
_create_mbox_benchmark(false);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _create_mbox_sd_bench(lv_obj_t * btn)
|
||||
{
|
||||
_create_mbox_benchmark(true);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
{
|
||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_CHIP" Internal eMMC Info");
|
||||
lv_win_add_btn(win, NULL, SYMBOL_CHIP" Benchmark", _create_mbox_emmc_bench);
|
||||
|
||||
lv_obj_t *desc = lv_cont_create(win, NULL);
|
||||
lv_obj_set_size(desc, LV_HOR_RES / 2 / 6 * 2, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
|
||||
@@ -557,11 +851,11 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_static_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
|
||||
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
|
||||
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
|
||||
}
|
||||
else
|
||||
@@ -643,7 +937,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 4 * 4, LV_VER_RES - (LV_DPI * 11 / 7) - 5);
|
||||
|
||||
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
|
||||
lv_ta_set_style(lb_desc2, LV_TA_STYLE_BG, &monospace_text);
|
||||
lv_label_set_style(lb_desc2, &monospace_text);
|
||||
|
||||
u32 boot_size = storage.ext_csd.boot_mult << 17;
|
||||
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17;
|
||||
@@ -654,28 +948,34 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
s_printf(txt_buf + strlen(txt_buf), "0: #96FF00 GPP# Size: %5d MiB (Sect: 0x%08X)\n\n", storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt);
|
||||
s_printf(txt_buf + strlen(txt_buf), "#00DDFF GPP (eMMC USER) Partition Table:#\n");
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
int gpp_idx = 0;
|
||||
|
||||
u32 idx = 0;
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
if (gpp_idx < 2)
|
||||
if (idx > 10)
|
||||
{
|
||||
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#", gpp_idx++, part->name);
|
||||
if (gpp_idx < 2)
|
||||
s_printf(txt_buf + strlen(txt_buf), " ");
|
||||
s_printf(txt_buf + strlen(txt_buf), " Size: %d MiB (Sect: 0x%4X), Range: %06X-%06X\n",
|
||||
s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Table truncated!#");
|
||||
break;
|
||||
}
|
||||
|
||||
if (part->index < 2)
|
||||
{
|
||||
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s# ", part->index, part->name);
|
||||
s_printf(txt_buf + strlen(txt_buf), " Size: %d MiB (Sect: 0x%X), Start: %06X\n",
|
||||
(part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
|
||||
part->lba_end - part->lba_start + 1, part->lba_start, part->lba_end);
|
||||
part->lba_end - part->lba_start + 1, part->lba_start);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#\n Size: %6d MiB (Sect: 0x%07X), Range: %07X-%07X\n",
|
||||
gpp_idx++, part->name, (part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
|
||||
part->lba_end - part->lba_start + 1, part->lba_start, part->lba_end);
|
||||
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#\n Size: %7d MiB (Sect: 0x%07X), Start: %07X\n",
|
||||
part->index, part->name, (part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
|
||||
part->lba_end - part->lba_start + 1, part->lba_start);
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
|
||||
@@ -693,6 +993,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
{
|
||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_SD" microSD Card Info");
|
||||
lv_win_add_btn(win, NULL, SYMBOL_SD" Benchmark", _create_mbox_sd_bench);
|
||||
|
||||
lv_obj_t *desc = lv_cont_create(win, NULL);
|
||||
lv_obj_set_size(desc, LV_HOR_RES / 2 / 5 * 2, LV_VER_RES - (LV_DPI * 11 / 7) * 5 / 2);
|
||||
@@ -701,7 +1002,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_recolor(lb_desc, true);
|
||||
|
||||
lv_label_set_static_text(lb_desc, "#D4FF00 Please wait...#");
|
||||
lv_label_set_text(lb_desc, "#D4FF00 Please wait...#");
|
||||
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
|
||||
|
||||
// Disable buttons.
|
||||
@@ -710,10 +1011,10 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
manual_system_maintenance(true);
|
||||
|
||||
if (!sd_mount())
|
||||
lv_label_set_static_text(lb_desc, "#FFDD00 Failed to init SD!#");
|
||||
lv_label_set_text(lb_desc, "#FFDD00 Failed to init SD!#");
|
||||
else
|
||||
{
|
||||
lv_label_set_static_text(lb_desc,
|
||||
lv_label_set_text(lb_desc,
|
||||
"#00DDFF Card IDentification:#\n"
|
||||
"Vendor ID:\n"
|
||||
"OEM ID:\n"
|
||||
@@ -729,7 +1030,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
|
||||
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
|
||||
s_printf(txt_buf,"\n%02x\n%c%c\n%c%c%c%c%c\n%X\n%X\n%08x\n%02d/%04d",
|
||||
sd_storage.cid.manfid, (sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF,
|
||||
@@ -768,7 +1069,6 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
|
||||
lv_obj_t * lb_val2 = lv_label_create(val2, lb_desc);
|
||||
|
||||
|
||||
s_printf(txt_buf,
|
||||
"#00DDFF v%d.0#\n%02X\n%d MiB\n%d\n%d MB/s (%d MHz)\n%d\nU%d\nV%d\nA%d\n%d",
|
||||
sd_storage.csd.structure + 1, sd_storage.csd.cmdclass, sd_storage.sec_cnt >> 11,
|
||||
@@ -792,17 +1092,16 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
lv_obj_set_size(desc3, LV_HOR_RES / 2 / 2 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||
|
||||
lv_obj_t * lb_desc3 = lv_label_create(desc3, lb_desc);
|
||||
|
||||
lv_label_set_static_text(lb_desc3, "#D4FF00 Acquiring FAT volume info...#");
|
||||
|
||||
lv_label_set_text(lb_desc3, "#D4FF00 Acquiring FAT volume info...#");
|
||||
lv_obj_set_width(lb_desc3, lv_obj_get_width(desc3));
|
||||
|
||||
lv_obj_align(desc3, desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
|
||||
|
||||
manual_system_maintenance(true);
|
||||
|
||||
f_getfree("", &sd_fs.free_clst, NULL);
|
||||
|
||||
lv_label_set_static_text(lb_desc3,
|
||||
lv_label_set_text(lb_desc3,
|
||||
"#00DDFF Found FAT volume:#\n"
|
||||
"Filesystem:\n"
|
||||
"Cluster:\n"
|
||||
@@ -827,6 +1126,36 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
lv_obj_set_width(lb_val3, lv_obj_get_width(val3));
|
||||
lv_obj_align(val3, desc3, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||
|
||||
lv_obj_t *desc4 = lv_cont_create(win, NULL);
|
||||
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 2 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||
|
||||
lv_obj_t * lb_desc4 = lv_label_create(desc4, lb_desc);
|
||||
lv_label_set_text(lb_desc4, "#D4FF00 Acquiring FAT volume info...#");
|
||||
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
|
||||
|
||||
lv_label_set_text(lb_desc4,
|
||||
"#00DDFF SDMMC1 Error Counts:#\n"
|
||||
"Init fails:\n"
|
||||
"Read/Write fails:\n"
|
||||
"Read/Write errors:"
|
||||
);
|
||||
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 5 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
|
||||
lv_obj_align(desc4, val3, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
|
||||
|
||||
lv_obj_t *val4 = lv_cont_create(win, NULL);
|
||||
lv_obj_set_size(val4, LV_HOR_RES / 13 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||
|
||||
lv_obj_t * lb_val4 = lv_label_create(val4, lb_desc);
|
||||
|
||||
u16 *sd_errors = sd_get_error_count();
|
||||
s_printf(txt_buf, "\n%d\n%d\n%d", sd_errors[0], sd_errors[1], sd_errors[2]);
|
||||
|
||||
lv_label_set_text(lb_val4, txt_buf);
|
||||
|
||||
lv_obj_set_width(lb_val4, lv_obj_get_width(val4));
|
||||
lv_obj_align(val4, desc4, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
|
||||
|
||||
free(txt_buf);
|
||||
sd_unmount(false);
|
||||
}
|
||||
@@ -870,7 +1199,7 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
|
||||
|
||||
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
int value = 0;
|
||||
|
||||
max17050_get_property(MAX17050_RepSOC, &value);
|
||||
@@ -1038,7 +1367,7 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
|
||||
lv_label_set_static_text(label_sep, "");
|
||||
|
||||
lv_obj_t *label_txt = lv_label_create(h1, NULL);
|
||||
lv_label_set_static_text(label_txt, "SoC Info");
|
||||
lv_label_set_static_text(label_txt, "SoC & HW Info");
|
||||
lv_obj_set_style(label_txt, th->label.prim);
|
||||
lv_obj_align(label_txt, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, 0);
|
||||
|
||||
@@ -1088,7 +1417,7 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
|
||||
lv_obj_t *btn3 = lv_btn_create(h1, btn);
|
||||
label_btn = lv_label_create(btn3, NULL);
|
||||
lv_btn_set_fit(btn3, true, true);
|
||||
lv_label_set_static_text(label_btn, SYMBOL_CIRCUIT" Fuses ");
|
||||
lv_label_set_static_text(label_btn, SYMBOL_CIRCUIT" HW & Fuses");
|
||||
lv_obj_align(btn3, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 2);
|
||||
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _create_window_fuses_info_status);
|
||||
|
||||
@@ -1096,15 +1425,15 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
|
||||
lv_obj_t *btn4 = lv_btn_create(h1, btn);
|
||||
label_btn = lv_label_create(btn4, NULL);
|
||||
lv_label_set_static_text(label_btn, SYMBOL_SHUFFLE" KFuses");
|
||||
lv_obj_align(btn4, btn3, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 123 / 100, 0);
|
||||
lv_obj_align(btn4, btn3, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 46 / 100, 0);
|
||||
lv_btn_set_action(btn4, LV_BTN_ACTION_CLICK, _kfuse_dump_window_action);
|
||||
|
||||
lv_obj_t *label_txt4 = lv_label_create(h1, NULL);
|
||||
lv_label_set_recolor(label_txt4, true);
|
||||
lv_label_set_static_text(label_txt4,
|
||||
"View and dump your cached fuses and KFuses.\n"
|
||||
"Fuses contain info about your SoC and device and KFuses\n"
|
||||
"contain downstream and upstream HDCP keys used by HDMI.");
|
||||
"View and dump your cached #C7EA46 Fuses# and #C7EA46 KFuses#.\n"
|
||||
"Fuses contain info about your SoC and device and KFuses contain HDCP.\n"
|
||||
"You can also see info about #C7EA46 DRAM#, #C7EA46 Screen# and #C7EA46 Touch panel#.");
|
||||
lv_obj_set_style(label_txt4, &hint_small_style);
|
||||
lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
|
||||
|
||||
@@ -1152,8 +1481,8 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
|
||||
lv_obj_t *label_txt5 = lv_label_create(h2, NULL);
|
||||
lv_label_set_recolor(label_txt5, true);
|
||||
lv_label_set_static_text(label_txt5,
|
||||
"View info about your eMMC or microSD and additionally\n"
|
||||
"view their partition list and info.");
|
||||
"View info about your eMMC or microSD and their partition list.\n"
|
||||
"Additionally you can benchmark read speeds.");
|
||||
lv_obj_set_style(label_txt5, &hint_small_style);
|
||||
lv_obj_align(label_txt5, btn5, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
|
||||
|
||||
|
||||
@@ -14,18 +14,22 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "gui.h"
|
||||
#include "../config/config.h"
|
||||
#include "../config/ini.h"
|
||||
#include "../gfx/di.h"
|
||||
#include "../input/joycon.h"
|
||||
#include "../libs/lvgl/lvgl.h"
|
||||
#include "../mem/heap.h"
|
||||
#include "../storage/nx_sd.h"
|
||||
#include "../utils/list.h"
|
||||
#include "../utils/sprintf.h"
|
||||
#include "../utils/types.h"
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
extern bool sd_mount();
|
||||
extern void sd_unmount(bool deinit);
|
||||
extern nyx_config n_cfg;
|
||||
|
||||
static lv_obj_t *autoboot_btn;
|
||||
static bool autoboot_first_time = true;
|
||||
@@ -58,6 +62,20 @@ static lv_res_t auto_nogc_toggle(lv_obj_t *btn)
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _update_r2p_action(lv_obj_t *btn)
|
||||
{
|
||||
h_cfg.updater2p = !h_cfg.updater2p;
|
||||
|
||||
if (!h_cfg.updater2p)
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
else
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
|
||||
nyx_generic_onoff_toggle(btn);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _win_autoboot_close_action(lv_obj_t * btn)
|
||||
{
|
||||
if (!h_cfg.autoboot)
|
||||
@@ -71,6 +89,8 @@ static lv_res_t _win_autoboot_close_action(lv_obj_t * btn)
|
||||
|
||||
lv_obj_del(win);
|
||||
|
||||
close_btn = NULL;
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
@@ -87,7 +107,7 @@ lv_obj_t *create_window_autoboot(const char *win_title)
|
||||
lv_win_set_style(win, LV_WIN_STYLE_BG, &win_bg_style);
|
||||
lv_obj_set_size(win, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
lv_win_add_btn(win, NULL, SYMBOL_CLOSE" Close", _win_autoboot_close_action);
|
||||
close_btn = lv_win_add_btn(win, NULL, SYMBOL_CLOSE" Close", _win_autoboot_close_action);
|
||||
|
||||
return win;
|
||||
}
|
||||
@@ -274,7 +294,573 @@ static lv_res_t _slider_brightness_action(lv_obj_t * slider)
|
||||
|
||||
static lv_res_t _data_verification_action(lv_obj_t *ddlist)
|
||||
{
|
||||
h_cfg.verification = lv_ddlist_get_selected(ddlist);
|
||||
n_cfg.verification = lv_ddlist_get_selected(ddlist);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
void create_flat_button(lv_obj_t *parent, lv_obj_t *btn, lv_color_t color, lv_action_t action)
|
||||
{
|
||||
lv_style_t *btn_onoff_rel_hos_style = malloc(sizeof(lv_style_t));
|
||||
lv_style_t *btn_onoff_pr_hos_style = malloc(sizeof(lv_style_t));
|
||||
lv_style_copy(btn_onoff_rel_hos_style, lv_theme_get_current()->btn.rel);
|
||||
btn_onoff_rel_hos_style->body.main_color = color;
|
||||
btn_onoff_rel_hos_style->body.grad_color = btn_onoff_rel_hos_style->body.main_color;
|
||||
btn_onoff_rel_hos_style->body.padding.hor = 0;
|
||||
btn_onoff_rel_hos_style->body.radius = 0;
|
||||
|
||||
lv_style_copy(btn_onoff_pr_hos_style, lv_theme_get_current()->btn.pr);
|
||||
btn_onoff_pr_hos_style->body.main_color = color;
|
||||
btn_onoff_pr_hos_style->body.grad_color = btn_onoff_pr_hos_style->body.main_color;
|
||||
btn_onoff_pr_hos_style->body.padding.hor = 0;
|
||||
btn_onoff_pr_hos_style->body.border.color = LV_COLOR_GRAY;
|
||||
btn_onoff_pr_hos_style->body.border.width = 4;
|
||||
btn_onoff_pr_hos_style->body.radius = 0;
|
||||
|
||||
lv_btn_set_style(btn, LV_BTN_STYLE_REL, btn_onoff_rel_hos_style);
|
||||
lv_btn_set_style(btn, LV_BTN_STYLE_PR, btn_onoff_pr_hos_style);
|
||||
lv_btn_set_style(btn, LV_BTN_STYLE_TGL_REL, btn_onoff_rel_hos_style);
|
||||
lv_btn_set_style(btn, LV_BTN_STYLE_TGL_PR, btn_onoff_pr_hos_style);
|
||||
|
||||
lv_btn_set_fit(btn, false, true);
|
||||
lv_obj_set_width(btn, lv_obj_get_height(btn));
|
||||
lv_btn_set_toggle(btn, true);
|
||||
|
||||
if (action)
|
||||
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, action);
|
||||
}
|
||||
|
||||
typedef struct _color_test_ctxt
|
||||
{
|
||||
u16 hue;
|
||||
lv_obj_t *label;
|
||||
lv_obj_t *icons;
|
||||
lv_obj_t *slider;
|
||||
lv_obj_t *button;
|
||||
lv_obj_t *hue_slider;
|
||||
lv_obj_t *hue_label;
|
||||
} color_test_ctxt;
|
||||
|
||||
color_test_ctxt color_test;
|
||||
|
||||
static lv_res_t _save_theme_color_action(lv_obj_t *btn)
|
||||
{
|
||||
n_cfg.themecolor = color_test.hue;
|
||||
|
||||
// Save nyx config.
|
||||
create_nyx_config_entry();
|
||||
|
||||
reload_nyx();
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static void _test_nyx_color(u16 hue)
|
||||
{
|
||||
lv_color_t color = lv_color_hsv_to_rgb(hue, 100, 100);
|
||||
static lv_style_t btn_tgl_test;
|
||||
lv_style_copy(&btn_tgl_test, lv_btn_get_style(color_test.button, LV_BTN_STATE_TGL_PR));
|
||||
btn_tgl_test.body.border.color = color;
|
||||
btn_tgl_test.text.color = color;
|
||||
lv_btn_set_style(color_test.button, LV_BTN_STATE_TGL_PR, &btn_tgl_test);
|
||||
|
||||
static lv_style_t txt_test;
|
||||
lv_style_copy(&txt_test, lv_label_get_style(color_test.label));
|
||||
txt_test.text.color = color;
|
||||
lv_obj_set_style(color_test.label, &txt_test);
|
||||
lv_obj_set_style(color_test.icons, &txt_test);
|
||||
|
||||
static lv_style_t slider_test, slider_ind;
|
||||
lv_style_copy(&slider_test, lv_slider_get_style(color_test.slider, LV_SLIDER_STYLE_KNOB));
|
||||
lv_style_copy(&slider_ind, lv_slider_get_style(color_test.slider, LV_SLIDER_STYLE_INDIC));
|
||||
slider_test.body.main_color = color;
|
||||
slider_test.body.grad_color = slider_test.body.main_color;
|
||||
slider_ind.body.main_color = lv_color_hsv_to_rgb(hue, 100, 72);
|
||||
slider_ind.body.grad_color = slider_ind.body.main_color;
|
||||
lv_slider_set_style(color_test.slider, LV_SLIDER_STYLE_KNOB, &slider_test);
|
||||
lv_slider_set_style(color_test.slider, LV_SLIDER_STYLE_INDIC, &slider_ind);
|
||||
}
|
||||
|
||||
static lv_res_t _slider_hue_action(lv_obj_t *slider)
|
||||
{
|
||||
if (color_test.hue != lv_slider_get_value(slider))
|
||||
{
|
||||
color_test.hue = lv_slider_get_value(slider);
|
||||
_test_nyx_color(color_test.hue);
|
||||
char hue[8];
|
||||
s_printf(hue, "%03d", color_test.hue);
|
||||
lv_label_set_text(color_test.hue_label, hue);
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _preset_hue_action(lv_obj_t *btn)
|
||||
{
|
||||
lv_btn_ext_t *ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
if (color_test.hue != ext->idx)
|
||||
{
|
||||
color_test.hue = ext->idx;
|
||||
_test_nyx_color(color_test.hue);
|
||||
char hue[8];
|
||||
s_printf(hue, "%03d", color_test.hue);
|
||||
lv_label_set_text(color_test.hue_label, hue);
|
||||
lv_bar_set_value(color_test.hue_slider, color_test.hue);
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
const u16 theme_colors[17] = {
|
||||
4, 13, 23, 33, 43, 54, 66, 89, 124, 167, 187, 200, 208, 231, 261, 291, 341
|
||||
};
|
||||
|
||||
static lv_res_t _create_window_nyx_colors(lv_obj_t *btn)
|
||||
{
|
||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_COPY" Choose a Nyx Color Theme");
|
||||
lv_win_add_btn(win, NULL, SYMBOL_SAVE" Save & Reload", _save_theme_color_action);
|
||||
|
||||
// Set current color.
|
||||
color_test.hue = n_cfg.themecolor;
|
||||
|
||||
lv_obj_t *sep = lv_label_create(win, NULL);
|
||||
lv_label_set_static_text(sep, "");
|
||||
lv_obj_align(sep, NULL, LV_ALIGN_IN_TOP_MID, 0, 0);
|
||||
|
||||
// Create container to keep content inside.
|
||||
lv_obj_t *h1 = lv_cont_create(win, NULL);
|
||||
lv_obj_set_size(h1, LV_HOR_RES - (LV_DPI * 8 / 10), LV_VER_RES / 7);
|
||||
|
||||
// Create color preset buttons.
|
||||
lv_obj_t *color_btn = lv_btn_create(h1, NULL);
|
||||
lv_btn_ext_t *ext = lv_obj_get_ext_attr(color_btn);
|
||||
ext->idx = theme_colors[0];
|
||||
create_flat_button(h1, color_btn, lv_color_hsv_to_rgb(theme_colors[0], 100, 100), _preset_hue_action);
|
||||
lv_obj_t *color_btn2;
|
||||
|
||||
for (u32 i = 1; i < 17; i++)
|
||||
{
|
||||
color_btn2 = lv_btn_create(h1, NULL);
|
||||
ext = lv_obj_get_ext_attr(color_btn2);
|
||||
ext->idx = theme_colors[i];
|
||||
create_flat_button(h1, color_btn2, lv_color_hsv_to_rgb(theme_colors[i], 100, 100), _preset_hue_action);
|
||||
lv_obj_align(color_btn2, color_btn, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||
color_btn = color_btn2;
|
||||
}
|
||||
|
||||
lv_obj_align(h1, sep, LV_ALIGN_OUT_BOTTOM_MID, 0, LV_DPI / 4);
|
||||
|
||||
// Create hue slider.
|
||||
lv_obj_t * slider = lv_slider_create(win, NULL);
|
||||
lv_obj_set_width(slider, 1070);
|
||||
lv_obj_set_height(slider, LV_DPI * 4 / 10);
|
||||
lv_bar_set_range(slider, 0, 359);
|
||||
lv_bar_set_value(slider, color_test.hue);
|
||||
lv_slider_set_action(slider, _slider_hue_action);
|
||||
lv_obj_align(slider, h1, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
color_test.hue_slider = slider;
|
||||
|
||||
// Create hue label.
|
||||
lv_obj_t *hue_text_label = lv_label_create(win, NULL);
|
||||
lv_obj_align(hue_text_label, slider, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 24 / 100, 0);
|
||||
char hue[8];
|
||||
s_printf(hue, "%03d", color_test.hue);
|
||||
lv_label_set_text(hue_text_label, hue);
|
||||
color_test.hue_label = hue_text_label;
|
||||
|
||||
// Create sample text.
|
||||
lv_obj_t *h2 = lv_cont_create(win, NULL);
|
||||
lv_obj_set_size(h2, LV_HOR_RES - (LV_DPI * 8 / 10), LV_VER_RES / 3);
|
||||
lv_obj_align(h2, slider, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI);
|
||||
|
||||
lv_obj_t *lbl_sample = lv_label_create(h2, NULL);
|
||||
lv_label_set_static_text(lbl_sample, "Sample:");
|
||||
|
||||
lv_obj_t *lbl_test = lv_label_create(h2, NULL);
|
||||
lv_label_set_long_mode(lbl_test, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_static_text(lbl_test,
|
||||
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
|
||||
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
|
||||
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris "
|
||||
"nisi ut aliquip ex ea commodo consequat.");
|
||||
lv_obj_set_width(lbl_test, lv_obj_get_width(h2) - LV_DPI * 6 / 10);
|
||||
lv_obj_align(lbl_test, lbl_sample, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5);
|
||||
color_test.label = lbl_test;
|
||||
|
||||
// Create sample icons.
|
||||
lv_obj_t *lbl_icons = lv_label_create(h2, NULL);
|
||||
lv_label_set_static_text(lbl_icons,
|
||||
SYMBOL_BRIGHTNESS SYMBOL_CHARGE SYMBOL_FILE SYMBOL_DRIVE SYMBOL_FILE_CODE
|
||||
SYMBOL_EDIT SYMBOL_HINT SYMBOL_DRIVE SYMBOL_KEYBOARD SYMBOL_POWER);
|
||||
lv_obj_align(lbl_icons, lbl_test, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI * 2 / 5);
|
||||
color_test.icons = lbl_icons;
|
||||
|
||||
// Create sample slider.
|
||||
lv_obj_t *slider_test = lv_slider_create(h2, NULL);
|
||||
lv_obj_align(slider_test, lbl_test, LV_ALIGN_OUT_BOTTOM_MID, 0, LV_DPI * 2 / 5);
|
||||
lv_obj_set_click(slider_test, false);
|
||||
lv_bar_set_value(slider_test, 60);
|
||||
color_test.slider = slider_test;
|
||||
|
||||
// Create sample button.
|
||||
lv_obj_t *btn_test = lv_btn_create(h2, NULL);
|
||||
lv_btn_set_state(btn_test, LV_BTN_STATE_TGL_PR);
|
||||
lv_obj_align(btn_test, lbl_test, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, LV_DPI / 5);
|
||||
lv_label_create(btn_test, NULL);
|
||||
lv_obj_set_click(btn_test, false);
|
||||
color_test.button = btn_test;
|
||||
|
||||
_test_nyx_color(color_test.hue);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
lv_obj_t *epoch_ta;
|
||||
static lv_res_t _create_mbox_clock_edit_action(lv_obj_t * btns, const char * txt)
|
||||
{
|
||||
int btn_idx = lv_btnm_get_pressed(btns);
|
||||
|
||||
if (btn_idx == 1)
|
||||
n_cfg.timeoff = strtol(lv_ta_get_text(epoch_ta), NULL, 16);
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static lv_res_t _create_mbox_clock_edit(lv_obj_t *btn)
|
||||
{
|
||||
lv_style_t *darken;
|
||||
darken = malloc(sizeof(lv_style_t));
|
||||
lv_style_copy(darken, &lv_style_plain);
|
||||
darken->body.main_color = LV_COLOR_BLACK;
|
||||
darken->body.grad_color = darken->body.main_color;
|
||||
darken->body.opa = LV_OPA_30;
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char * mbox_btn_map[] = { "\211", "\222Done", "\222Cancel", "\211", "" };
|
||||
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
|
||||
|
||||
lv_mbox_set_text(mbox, "Type the #C7EA46 epoch# offset in HEX s32:");
|
||||
|
||||
lv_obj_t *ta = lv_ta_create(mbox, NULL);
|
||||
lv_obj_set_size(ta, LV_HOR_RES / 5, LV_VER_RES / 10);
|
||||
lv_obj_align(ta, NULL, LV_ALIGN_IN_TOP_RIGHT, -LV_DPI / 10, LV_DPI / 10);
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_LINE);
|
||||
lv_ta_set_one_line(ta, true);
|
||||
epoch_ta = ta;
|
||||
|
||||
static char epoch_off[16];
|
||||
s_printf(epoch_off, "%X", n_cfg.timeoff);
|
||||
lv_ta_set_text(ta, epoch_off);
|
||||
lv_ta_set_max_length(ta, 8);
|
||||
|
||||
lv_obj_t *kb = lv_kb_create(mbox, NULL);
|
||||
lv_obj_set_size(kb, 2 * LV_HOR_RES / 3, LV_VER_RES / 3);
|
||||
lv_obj_align(kb, ta, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, LV_DPI);
|
||||
lv_kb_set_mode(kb, LV_KB_MODE_HEX);
|
||||
lv_kb_set_ta(kb, ta);
|
||||
lv_kb_set_cursor_manage(kb, true);
|
||||
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_mbox_clock_edit_action); // Important. After set_text.
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
|
||||
{
|
||||
FIL fp;
|
||||
jc_gamepad_rpt_t *jc_pad = jc_get_bt_pairing_info();
|
||||
|
||||
int error = !sd_mount();
|
||||
|
||||
char *data = (char *)malloc(0x4000);
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
// Save binary dump.
|
||||
memcpy(data, &jc_pad->bt_conn_l, sizeof(jc_bt_conn_t));
|
||||
memcpy(data + sizeof(jc_bt_conn_t), &jc_pad->bt_conn_r, sizeof(jc_bt_conn_t));
|
||||
|
||||
f_mkdir("switchroot");
|
||||
error = sd_save_to_file((u8 *)data, sizeof(jc_bt_conn_t) * 2, "switchroot/joycon_mac.bin");
|
||||
|
||||
// Save readable dump.
|
||||
jc_bt_conn_t *bt = &jc_pad->bt_conn_l;
|
||||
s_printf(data,
|
||||
"[joycon_00]\ntype=%d\nmac=%02X:%02X:%02X:%02X:%02X:%02X\n"
|
||||
"host=%02X:%02X:%02X:%02X:%02X:%02X\n"
|
||||
"ltk=%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n\n",
|
||||
bt->type, bt->mac[0], bt->mac[1], bt->mac[2], bt->mac[3], bt->mac[4], bt->mac[5],
|
||||
bt->host_mac[0], bt->host_mac[1], bt->host_mac[2], bt->host_mac[3], bt->host_mac[4], bt->host_mac[5],
|
||||
bt->ltk[0], bt->ltk[1], bt->ltk[2], bt->ltk[3], bt->ltk[4], bt->ltk[5], bt->ltk[6], bt->ltk[7],
|
||||
bt->ltk[8], bt->ltk[9], bt->ltk[10], bt->ltk[11], bt->ltk[12], bt->ltk[13], bt->ltk[14], bt->ltk[15]);
|
||||
bt = &jc_pad->bt_conn_r;
|
||||
s_printf(data + strlen(data),
|
||||
"[joycon_01]\ntype=%d\nmac=%02X:%02X:%02X:%02X:%02X:%02X\n"
|
||||
"host=%02X:%02X:%02X:%02X:%02X:%02X\n"
|
||||
"ltk=%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
bt->type, bt->mac[0], bt->mac[1], bt->mac[2], bt->mac[3], bt->mac[4], bt->mac[5],
|
||||
bt->host_mac[0], bt->host_mac[1], bt->host_mac[2], bt->host_mac[3], bt->host_mac[4], bt->host_mac[5],
|
||||
bt->ltk[0], bt->ltk[1], bt->ltk[2], bt->ltk[3], bt->ltk[4], bt->ltk[5], bt->ltk[6], bt->ltk[7],
|
||||
bt->ltk[8], bt->ltk[9], bt->ltk[10], bt->ltk[11], bt->ltk[12], bt->ltk[13], bt->ltk[14], bt->ltk[15]);
|
||||
|
||||
if (!error)
|
||||
error = f_open(&fp, "switchroot/joycon_mac.ini", FA_WRITE | FA_CREATE_ALWAYS);
|
||||
if (!error)
|
||||
{
|
||||
f_puts(data, &fp);
|
||||
f_close(&fp);
|
||||
}
|
||||
|
||||
sd_unmount(false);
|
||||
}
|
||||
|
||||
lv_style_t *darken;
|
||||
darken = (lv_style_t *)malloc(sizeof(lv_style_t));
|
||||
lv_style_copy(darken, &lv_style_plain);
|
||||
darken->body.main_color = LV_COLOR_BLACK;
|
||||
darken->body.grad_color = darken->body.main_color;
|
||||
darken->body.opa = LV_OPA_30;
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char * mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
|
||||
|
||||
u32 joycon_found = jc_pad->bt_conn_l.type ? 1 : 0;
|
||||
if (jc_pad->bt_conn_r.type)
|
||||
joycon_found++;
|
||||
|
||||
if (error)
|
||||
s_printf(txt_buf, "#FFDD00 Failed to dump to# Joy-Con pairing info#FFDD00 !#\nError: %d", error);
|
||||
else
|
||||
s_printf(txt_buf,
|
||||
"Dumping to SD card finished!\n"
|
||||
"Found %d Joycon!\n\n"
|
||||
"Saved to: #C7EA46 switchroot/joycon_mac.bin/ini#", joycon_found);
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
free(txt_buf);
|
||||
free(data);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _home_screen_action(lv_obj_t *ddlist)
|
||||
{
|
||||
n_cfg.home_screen = lv_ddlist_get_selected(ddlist);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t _save_nyx_options_action(lv_obj_t *btn)
|
||||
{
|
||||
static const char * mbox_btn_map[] = {"\211", "\222OK!", "\211", ""};
|
||||
lv_obj_t * mbox = lv_mbox_create(lv_scr_act(), NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
|
||||
int res = !create_nyx_config_entry();
|
||||
|
||||
if (res)
|
||||
lv_mbox_set_text(mbox, "#FF8000 Nyx Configuration#\n\n#96FF00 The configuration was saved to sd card!#");
|
||||
else
|
||||
lv_mbox_set_text(mbox, "#FF8000 Nyx Configuration#\n\n#FFDD00 Failed to save the configuration#\n#FFDD00 to sd card!#");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, NULL);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
lv_res_t create_win_nyx_options(lv_obj_t *parrent_btn)
|
||||
{
|
||||
lv_theme_t *th = lv_theme_get_current();
|
||||
|
||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_HOME" Nyx Options");
|
||||
|
||||
static lv_style_t h_style;
|
||||
lv_style_copy(&h_style, &lv_style_transp);
|
||||
h_style.body.padding.inner = 0;
|
||||
h_style.body.padding.hor = LV_DPI - (LV_DPI / 4);
|
||||
h_style.body.padding.ver = LV_DPI / 6;
|
||||
|
||||
// Create containers to keep content inside.
|
||||
lv_obj_t * sw_h2 = lv_cont_create(win, NULL);
|
||||
lv_cont_set_style(sw_h2, &h_style);
|
||||
lv_cont_set_fit(sw_h2, false, true);
|
||||
lv_obj_set_width(sw_h2, (LV_HOR_RES / 9) * 4);
|
||||
lv_obj_set_click(sw_h2, false);
|
||||
lv_cont_set_layout(sw_h2, LV_LAYOUT_OFF);
|
||||
|
||||
lv_obj_t * sw_h3 = lv_cont_create(win, NULL);
|
||||
lv_cont_set_style(sw_h3, &h_style);
|
||||
lv_cont_set_fit(sw_h3, false, true);
|
||||
lv_obj_set_width(sw_h3, (LV_HOR_RES / 9) * 4);
|
||||
lv_obj_set_click(sw_h3, false);
|
||||
lv_cont_set_layout(sw_h3, LV_LAYOUT_OFF);
|
||||
lv_obj_align(sw_h3, sw_h2, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 11 / 25, 0);
|
||||
|
||||
lv_obj_t * l_cont = lv_cont_create(sw_h2, NULL);
|
||||
lv_cont_set_style(l_cont, &lv_style_transp_tight);
|
||||
lv_cont_set_fit(l_cont, true, true);
|
||||
lv_obj_set_click(l_cont, false);
|
||||
lv_cont_set_layout(l_cont, LV_LAYOUT_OFF);
|
||||
lv_obj_set_opa_scale(l_cont, LV_OPA_40);
|
||||
|
||||
lv_obj_t *label_sep = lv_label_create(sw_h2, NULL);
|
||||
lv_label_set_static_text(label_sep, "");
|
||||
|
||||
lv_obj_t *btn = lv_btn_create(sw_h2, NULL);
|
||||
lv_obj_t *label_btn = lv_label_create(btn, NULL);
|
||||
lv_btn_set_fit(btn, true, true);
|
||||
lv_label_set_static_text(label_btn, SYMBOL_COPY" Color Theme");
|
||||
lv_obj_align(btn, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -LV_DPI / 5 + 3);
|
||||
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _create_window_nyx_colors);
|
||||
|
||||
lv_obj_t *label_txt2 = lv_label_create(sw_h2, NULL);
|
||||
lv_label_set_recolor(label_txt2, true);
|
||||
lv_label_set_static_text(label_txt2, "Select a color for all #00FFC8 highlights# in Nyx.\n");
|
||||
lv_obj_set_style(label_txt2, &hint_small_style);
|
||||
lv_obj_align(label_txt2, btn, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3 - 8);
|
||||
|
||||
lv_obj_t *line_sep = lv_line_create(sw_h2, NULL);
|
||||
static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 4)) * 2, 0} };
|
||||
lv_line_set_points(line_sep, line_pp, 2);
|
||||
lv_line_set_style(line_sep, th->line.decor);
|
||||
lv_obj_align(line_sep, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 4);
|
||||
|
||||
lv_obj_t *label_txt = lv_label_create(l_cont, NULL);
|
||||
lv_label_set_static_text(label_txt, SYMBOL_HOME" Home Screen");
|
||||
lv_obj_set_style(label_txt, th->label.prim);
|
||||
lv_obj_align(label_txt, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4);
|
||||
|
||||
lv_obj_t *ddlist = lv_ddlist_create(l_cont, NULL);
|
||||
lv_obj_set_top(ddlist, true);
|
||||
lv_ddlist_set_draw_arrow(ddlist, true);
|
||||
lv_ddlist_set_options(ddlist,
|
||||
"Main menu \n"
|
||||
"All Configs\n"
|
||||
"Launch\n"
|
||||
"More Configs");
|
||||
lv_ddlist_set_selected(ddlist, n_cfg.home_screen);
|
||||
lv_ddlist_set_action(ddlist, _home_screen_action);
|
||||
lv_obj_align(ddlist, label_txt, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 2 / 3, 0);
|
||||
|
||||
label_txt2 = lv_label_create(l_cont, NULL);
|
||||
lv_label_set_recolor(label_txt2, true);
|
||||
lv_label_set_static_text(label_txt2,
|
||||
"Select what screen to show on Nyx boot.\n"
|
||||
"#FF8000 All Configs:# #C7EA46 Combines More configs into Launch empty slots.#\n"
|
||||
"#FF8000 Launch / More Configs:# #C7EA46 Uses the classic divided view.#");
|
||||
lv_obj_set_style(label_txt2, &hint_small_style);
|
||||
lv_obj_align(label_txt2, label_txt, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 4);
|
||||
|
||||
line_sep = lv_line_create(sw_h2, line_sep);
|
||||
lv_obj_align(line_sep, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 4);
|
||||
|
||||
lv_obj_t *btn2 = lv_btn_create(sw_h2, NULL);
|
||||
lv_obj_t *label_btn2 = lv_label_create(btn2, NULL);
|
||||
lv_btn_set_fit(btn2, true, true);
|
||||
lv_label_set_static_text(label_btn2, SYMBOL_CLOCK" Clock (HOS)");
|
||||
lv_obj_align(btn2, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4);
|
||||
lv_btn_set_action(btn2, LV_BTN_ACTION_CLICK, _create_mbox_clock_edit); //TODO: Add support.
|
||||
lv_btn_set_state(btn2, LV_BTN_STATE_INA); //TODO: Add support.
|
||||
|
||||
lv_obj_t *btn4 = lv_btn_create(sw_h2, btn2);
|
||||
label_btn2 = lv_label_create(btn4, NULL);
|
||||
lv_label_set_static_text(label_btn2, " "SYMBOL_EDIT" Manually ");
|
||||
lv_obj_align(btn4, btn2, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 8, 0);
|
||||
lv_btn_set_action(btn4, LV_BTN_ACTION_CLICK, _create_mbox_clock_edit);
|
||||
lv_btn_set_state(btn4, LV_BTN_STATE_REL);
|
||||
|
||||
label_txt2 = lv_label_create(sw_h2, NULL);
|
||||
lv_label_set_recolor(label_txt2, true);
|
||||
lv_label_set_static_text(label_txt2,
|
||||
"#FF8000 Clock (HOS):# #C7EA46 Change clock offset based on what HOS uses.#\n"
|
||||
"#FF8000 Manually:# #C7EA46 Edit the clock offset manually.#");
|
||||
lv_obj_set_style(label_txt2, &hint_small_style);
|
||||
lv_obj_align(label_txt2, btn2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 4);
|
||||
|
||||
label_sep = lv_label_create(sw_h3, NULL);
|
||||
lv_label_set_static_text(label_sep, "");
|
||||
|
||||
// Create Dump Joy-Con BT button.
|
||||
lv_obj_t *btn3 = lv_btn_create(sw_h3, NULL);
|
||||
lv_obj_t *label_btn3 = lv_label_create(btn3, NULL);
|
||||
lv_btn_set_fit(btn3, true, true);
|
||||
lv_label_set_static_text(label_btn3, SYMBOL_DOWNLOAD" Dump Joy-Con BT");
|
||||
lv_obj_align(btn3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -LV_DPI / 3);
|
||||
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _joycon_info_dump_action);
|
||||
|
||||
label_txt2 = lv_label_create(sw_h3, NULL);
|
||||
lv_label_set_recolor(label_txt2, true);
|
||||
lv_label_set_static_text(label_txt2,
|
||||
"Allows you to save the Switch and Joy-Con MAC addresses\n"
|
||||
"and the LTKs associated with them. For #C7EA46 Android# and #C7EA46 Linux#.");
|
||||
lv_obj_set_style(label_txt2, &hint_small_style);
|
||||
lv_obj_align(label_txt2, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 4);
|
||||
|
||||
line_sep = lv_line_create(sw_h3, line_sep);
|
||||
lv_obj_align(line_sep, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 4);
|
||||
|
||||
// Create Backup/Restore Verification list.
|
||||
label_txt = lv_label_create(sw_h3, NULL);
|
||||
lv_label_set_static_text(label_txt, SYMBOL_MODULES_ALT" Data Verification");
|
||||
lv_obj_set_style(label_txt, th->label.prim);
|
||||
lv_obj_align(label_txt, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4);
|
||||
|
||||
lv_obj_t *ddlist2 = lv_ddlist_create(sw_h3, NULL);
|
||||
lv_obj_set_top(ddlist2, true);
|
||||
lv_ddlist_set_draw_arrow(ddlist2, true);
|
||||
lv_ddlist_set_options(ddlist2,
|
||||
"Off (Fastest)\n"
|
||||
"Sparse (Fast) \n"
|
||||
"Full (Slow)\n"
|
||||
"Full (Hashes)");
|
||||
lv_ddlist_set_selected(ddlist2, n_cfg.verification);
|
||||
lv_obj_align(ddlist2, label_txt, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 3 / 8, 0);
|
||||
lv_ddlist_set_action(ddlist2, _data_verification_action);
|
||||
|
||||
label_txt2 = lv_label_create(sw_h3, NULL);
|
||||
lv_label_set_static_text(label_txt2, "Set the type of data verification done for backup and restore.\n"
|
||||
"Can be canceled without losing the backup/restore.\n");
|
||||
lv_obj_set_style(label_txt2, &hint_small_style);
|
||||
lv_obj_align(label_txt2, label_txt, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 4);
|
||||
|
||||
line_sep = lv_line_create(sw_h3, line_sep);
|
||||
lv_obj_align(line_sep, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 4);
|
||||
|
||||
lv_obj_t *btn5 = lv_btn_create(sw_h3, NULL);
|
||||
lv_obj_t *label_btn5 = lv_label_create(btn5, NULL);
|
||||
lv_btn_set_fit(btn5, true, true);
|
||||
lv_label_set_static_text(label_btn5, SYMBOL_EDIT" Save Options");
|
||||
lv_obj_align(btn5, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI * 31 / 21, LV_DPI * 6 / 8);
|
||||
lv_btn_set_action(btn5, LV_BTN_ACTION_CLICK, _save_nyx_options_action);
|
||||
|
||||
lv_obj_set_top(l_cont, true); // Set the ddlist container at top.
|
||||
lv_obj_set_parent(ddlist, l_cont); // Reorder ddlist.
|
||||
lv_obj_set_top(ddlist, true);
|
||||
lv_obj_set_top(ddlist2, true);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
@@ -389,7 +975,6 @@ void create_tab_options(lv_theme_t *th, lv_obj_t *parent)
|
||||
// Create Auto NoGC button.
|
||||
lv_obj_t *btn2 = lv_btn_create(sw_h2, NULL);
|
||||
nyx_create_onoff_button(th, sw_h2, btn2, SYMBOL_SHRK" Auto NoGC", auto_nogc_toggle, true);
|
||||
|
||||
lv_obj_align(btn2, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 10);
|
||||
|
||||
label_txt2 = lv_label_create(sw_h2, NULL);
|
||||
@@ -441,50 +1026,33 @@ void create_tab_options(lv_theme_t *th, lv_obj_t *parent)
|
||||
line_sep = lv_line_create(sw_h3, line_sep);
|
||||
lv_obj_align(line_sep, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 4);
|
||||
|
||||
// Create Backup/Restore Verification list.
|
||||
label_txt = lv_label_create(sw_h3, NULL);
|
||||
lv_label_set_static_text(label_txt, SYMBOL_MODULES_ALT" Data Verification");
|
||||
lv_obj_set_style(label_txt, th->label.prim);
|
||||
lv_obj_align(label_txt, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4);
|
||||
|
||||
lv_obj_t *ddlist2 = lv_ddlist_create(sw_h3, NULL);
|
||||
lv_obj_set_top(ddlist2, true);
|
||||
lv_ddlist_set_draw_arrow(ddlist2, true);
|
||||
lv_ddlist_set_options(ddlist2,
|
||||
"Off (Fastest)\n"
|
||||
"Sparse (Fast) \n"
|
||||
"Full (Slow)\n"
|
||||
"Full (Hashes)");
|
||||
lv_ddlist_set_selected(ddlist2, h_cfg.verification);
|
||||
lv_obj_align(ddlist2, label_txt, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 3 / 8, 0);
|
||||
lv_ddlist_set_action(ddlist2, _data_verification_action);
|
||||
|
||||
if (hekate_bg)
|
||||
{
|
||||
lv_ddlist_set_style(ddlist2, LV_DDLIST_STYLE_BG, &ddlist_transp_bg);
|
||||
lv_ddlist_set_style(ddlist2, LV_DDLIST_STYLE_BGO, &ddlist_transp_bg);
|
||||
lv_ddlist_set_style(ddlist2, LV_DDLIST_STYLE_PR, &ddlist_transp_sel);
|
||||
lv_ddlist_set_style(ddlist2, LV_DDLIST_STYLE_SEL, &ddlist_transp_sel);
|
||||
}
|
||||
// Create Update r2p button.
|
||||
lv_obj_t *btn4 = lv_btn_create(sw_h3, NULL);
|
||||
nyx_create_onoff_button(th, sw_h3, btn4, SYMBOL_REFRESH" Update Reboot 2 Payload", _update_r2p_action, true);
|
||||
lv_obj_align(btn4, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 10);
|
||||
|
||||
label_txt2 = lv_label_create(sw_h3, NULL);
|
||||
lv_label_set_static_text(label_txt2, "Set the type of data verification done for backup and restore.\n"
|
||||
"Can be canceled without losing the backup/restore.\n\n\n\n");
|
||||
lv_label_set_recolor(label_txt2, true);
|
||||
lv_label_set_static_text(label_txt2,
|
||||
"If #FF8000 FSS0# is used in the selected boot entry, the reboot 2 payload\n"
|
||||
"binary will be checked and forced to be updated to hekate.\n\n\n\n");
|
||||
lv_obj_set_style(label_txt2, &hint_small_style);
|
||||
lv_obj_align(label_txt2, label_txt, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 4);
|
||||
lv_obj_align(label_txt2, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 12);
|
||||
|
||||
// Set default loaded states.
|
||||
if (h_cfg.autohosoff)
|
||||
lv_btn_set_state(btn3, LV_BTN_STATE_TGL_REL);
|
||||
if (h_cfg.autonogc)
|
||||
lv_btn_set_state(btn2, LV_BTN_STATE_TGL_REL);
|
||||
if (h_cfg.updater2p)
|
||||
lv_btn_set_state(btn4, LV_BTN_STATE_TGL_REL);
|
||||
|
||||
nyx_generic_onoff_toggle(btn2);
|
||||
nyx_generic_onoff_toggle(btn3);
|
||||
nyx_generic_onoff_toggle(btn4);
|
||||
_autoboot_hide_delay_action(btn);
|
||||
|
||||
lv_obj_set_top(l_cont, true); // Set the ddlist container at top.
|
||||
lv_obj_set_parent(ddlist, l_cont); // Reorder ddlist.
|
||||
lv_obj_set_top(ddlist, true);
|
||||
lv_obj_set_top(ddlist2, true);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "../libs/lvgl/lvgl.h"
|
||||
|
||||
lv_res_t create_win_nyx_options(lv_obj_t *parrent_btn);
|
||||
void create_tab_options(lv_theme_t *th, lv_obj_t *parent);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,8 +19,12 @@
|
||||
|
||||
#include "../libs/lvgl/lvgl.h"
|
||||
|
||||
lv_obj_t *ums_mbox;
|
||||
|
||||
void create_tab_tools(lv_theme_t *th, lv_obj_t *parent);
|
||||
void sept_run_dump();
|
||||
void nyx_run_ums(void *param);
|
||||
void sept_run_dump(void *param);
|
||||
bool get_autorcm_status(bool change);
|
||||
lv_res_t action_ums_sd(lv_obj_t *btn);
|
||||
|
||||
#endif
|
||||
|
||||
2267
nyx/nyx_gui/frontend/gui_tools_partition_manager.c
Normal file
2267
nyx/nyx_gui/frontend/gui_tools_partition_manager.c
Normal file
File diff suppressed because it is too large
Load Diff
22
nyx/nyx_gui/frontend/gui_tools_partition_manager.h
Normal file
22
nyx/nyx_gui/frontend/gui_tools_partition_manager.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _GUI_TOOLS_PART_MANAGER_H_
|
||||
#define _GUI_TOOLS_PART_MANAGER_H_
|
||||
|
||||
lv_res_t create_window_partition_manager(lv_obj_t *btn);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-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,
|
||||
@@ -31,7 +31,11 @@
|
||||
|
||||
#include "di.inl"
|
||||
|
||||
static u32 _display_ver = 0;
|
||||
extern volatile nyx_storage_t *nyx_str;
|
||||
|
||||
static u32 _display_id = 0;
|
||||
|
||||
void display_end();
|
||||
|
||||
static void _display_dsi_wait(u32 timeout, u32 off, u32 mask)
|
||||
{
|
||||
@@ -41,8 +45,21 @@ static void _display_dsi_wait(u32 timeout, u32 off, u32 mask)
|
||||
usleep(5);
|
||||
}
|
||||
|
||||
static void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait)
|
||||
{
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = (param << 8) | cmd;
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
|
||||
if (wait)
|
||||
usleep(wait);
|
||||
}
|
||||
|
||||
void display_init()
|
||||
{
|
||||
// Check if display is already initialized.
|
||||
if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & 0x18000000)
|
||||
display_end();
|
||||
|
||||
// Power on.
|
||||
max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V.
|
||||
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL);
|
||||
@@ -60,16 +77,16 @@ void display_init()
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000; // Set enable clock DSIA_LP.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz).
|
||||
|
||||
// Disable deap power down.
|
||||
// Disable deep power down.
|
||||
PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000;
|
||||
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
|
||||
|
||||
// Config LCD and Backlight pins.
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE;
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE; // PULL_DOWN | 1
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; // PULL_DOWN
|
||||
|
||||
// Set Backlight +-5V pins mode and direction
|
||||
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
|
||||
@@ -87,14 +104,18 @@ void display_init()
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Enable Backlight EN.
|
||||
|
||||
// Power up supply regulator for display interface.
|
||||
MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG2) = 0;
|
||||
MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0;
|
||||
|
||||
// Set DISP1 clock source and parrent clock.
|
||||
exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4);
|
||||
// Set DISP1 clock source and parent clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT.
|
||||
u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 96 MHz.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2D0AAA; // PLLD_ENABLE_CLK.
|
||||
|
||||
// Setup display communication interfaces.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_3, 61);
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_dc_setup_win_config, 94);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config, 61);
|
||||
usleep(10000);
|
||||
|
||||
// Enable Backlight Reset.
|
||||
@@ -103,12 +124,10 @@ void display_init()
|
||||
|
||||
// Setups DSI packet configuration and request display id.
|
||||
DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204;
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x337; // MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
_display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, 3, 0);
|
||||
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x406; // MIPI_DCS_GET_DISPLAY_ID
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_READ, MIPI_DCS_GET_DISPLAY_ID, 0);
|
||||
_display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO);
|
||||
|
||||
DSI(_DSIREG(DSI_HOST_CONTROL)) = DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
|
||||
@@ -116,37 +135,71 @@ void display_init()
|
||||
|
||||
usleep(5000);
|
||||
|
||||
_display_ver = DSI(_DSIREG(DSI_RD_DATA));
|
||||
if (_display_ver == 0x10)
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_4, 43);
|
||||
// MIPI_DCS_GET_DISPLAY_ID reply is a long read, size 3 u32.
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
_display_id = DSI(_DSIREG(DSI_RD_DATA)); // Skip ack and msg type info and get the payload (display id).
|
||||
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x1105; // MIPI_DCS_EXIT_SLEEP_MODE
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
// Save raw Display ID to Nyx storage.
|
||||
nyx_str->info.disp_id = _display_id;
|
||||
|
||||
usleep(180000);
|
||||
// Decode Display ID.
|
||||
_display_id = ((_display_id >> 8) & 0xFF00) | (_display_id & 0xFF);
|
||||
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x2905; // MIPI_DCS_SET_DISPLAY_ON
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
if ((_display_id & 0xFF) == PANEL_JDI_LPM062M)
|
||||
_display_id = PANEL_JDI_LPM062M;
|
||||
|
||||
usleep(20000);
|
||||
// Initialize display panel.
|
||||
switch (_display_id)
|
||||
{
|
||||
case PANEL_JDI_LPM062M:
|
||||
exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43);
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
case PANEL_AUO_A062TAN01:
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000);
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // Enable extension cmd. (Pass: FF 83 94).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x739; // MIPI_DSI_DCS_LONG_WRITE: 7 bytes.
|
||||
if (_display_id == PANEL_INL_P062CCA_AZ1)
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // Set Power control. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
|
||||
else
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x143209; // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ2:
|
||||
case PANEL_AUO_A062TAN02:
|
||||
default: // Allow spare part displays to work.
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 120000);
|
||||
break;
|
||||
}
|
||||
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
|
||||
|
||||
// Configure PLLD for DISP1.
|
||||
exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3);
|
||||
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 460.8 MHz.
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20;
|
||||
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN.
|
||||
|
||||
// Finalize DSI configuration.
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_5, 21);
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4;
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_7, 10);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 21);
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; // PCD1 | div3.
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10);
|
||||
usleep(10000);
|
||||
|
||||
// Calibrate display communication pads.
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_9, 4);
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16);
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_pad_cal_config, 6);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_pad_cal_config, 4);
|
||||
exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_apply_dsi_cal_config, 16);
|
||||
usleep(10000);
|
||||
|
||||
// Enable video display controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113);
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_enable_config, 113);
|
||||
}
|
||||
|
||||
void display_backlight_pwm_init()
|
||||
@@ -197,25 +250,50 @@ void display_end()
|
||||
{
|
||||
display_backlight_brightness(0, 1000);
|
||||
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 1;
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE;
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; // MIPI_DCS_SET_DISPLAY_OFF
|
||||
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX;
|
||||
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; // Disable host cmd packet.
|
||||
|
||||
// De-initialize video controller.
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_13, 16);
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_disable_config, 17);
|
||||
exec_cfg((u32 *)DSI_BASE, _display_dsi_timing_deinit_config, 16);
|
||||
usleep(10000);
|
||||
|
||||
// De-initialize display panel.
|
||||
if (_display_ver == 0x10)
|
||||
exec_cfg((u32 *)DSI_BASE, _display_config_14, 22);
|
||||
switch (_display_id)
|
||||
{
|
||||
case PANEL_JDI_LPM062M:
|
||||
exec_cfg((u32 *)DSI_BASE, _display_deinit_config_jdi, 22);
|
||||
break;
|
||||
case PANEL_AUO_A062TAN01:
|
||||
exec_cfg((u32 *)DSI_BASE, _display_deinit_config_auo, 37);
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ2:
|
||||
case PANEL_AUO_A062TAN02:
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // Enable extension cmd. (Pass: FF 83 94).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
// Set Power.
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0xB39; // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
|
||||
if (_display_id == PANEL_INL_P062CCA_AZ2)
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // Set Power control. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
|
||||
else
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
|
||||
// Set Power control. (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG).
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x71143209;
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x114D31; // Set Power control. (Unknown).
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
usleep(5000);
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DSI(_DSIREG(DSI_WR_DATA)) = 0x1005; // MIPI_DCS_ENTER_SLEEP_MODE
|
||||
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
|
||||
|
||||
usleep(50000);
|
||||
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_ENTER_SLEEP_MODE, 50000);
|
||||
|
||||
// Disable display and backlight pins.
|
||||
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable.
|
||||
@@ -254,29 +332,104 @@ void display_color_screen(u32 color)
|
||||
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ;
|
||||
|
||||
usleep(35000);
|
||||
|
||||
display_backlight(true);
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer()
|
||||
u32 *display_init_framebuffer_pitch()
|
||||
{
|
||||
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer, 32);
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch, 34);
|
||||
|
||||
usleep(35000);
|
||||
|
||||
return (u32 *)NYX_FB_ADDRESS;
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer2()
|
||||
u32 *display_init_framebuffer_block()
|
||||
{
|
||||
// This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer2, 32);
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_block, 34);
|
||||
|
||||
usleep(35000);
|
||||
|
||||
return (u32 *)NYX_FB_ADDRESS;
|
||||
}
|
||||
|
||||
u32 *display_init_framebuffer_log()
|
||||
{
|
||||
// This configures the framebuffer @ LOG_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
|
||||
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_log, 20);
|
||||
|
||||
return (u32 *)LOG_FB_ADDRESS;
|
||||
}
|
||||
|
||||
void display_activate_console()
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window C.
|
||||
DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = WIN_ENABLE; // Enable window DD.
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0xFF80;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
|
||||
for (u32 i = 0xFF80; i < 0x10000; i++)
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_deactivate_console()
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window C.
|
||||
|
||||
for (u32 i = 0xFFFF; i > 0xFF7F; i--)
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0; // Disable window DD.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_init_cursor(void *crs_fb, u32 size)
|
||||
{
|
||||
// Setup cursor.
|
||||
DISPLAY_A(_DIREG(DC_DISP_CURSOR_START_ADDR)) = CURSOR_CLIPPING(CURSOR_CLIP_WIN_A) | size | ((u32)crs_fb >> 10);
|
||||
DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) =
|
||||
CURSOR_BLEND_R8G8B8A8 | CURSOR_BLEND_DST_FACTOR(CURSOR_BLEND_K1) | CURSOR_BLEND_SRC_FACTOR(CURSOR_BLEND_K1) | 0xFF;
|
||||
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) |= CURSOR_ENABLE;
|
||||
|
||||
// Arm and activate changes.
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_set_pos_cursor(u32 x, u32 y)
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_DISP_CURSOR_POSITION)) = x | (y << 16);
|
||||
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
|
||||
}
|
||||
|
||||
void display_deinit_cursor()
|
||||
{
|
||||
DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = 0;
|
||||
DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) &= ~CURSOR_ENABLE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE;
|
||||
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-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,
|
||||
@@ -24,6 +24,21 @@
|
||||
/*! Display registers. */
|
||||
#define _DIREG(reg) ((reg) * 4)
|
||||
|
||||
// Display controller scratch registers.
|
||||
#define DC_D_WINBUF_DD_SCRATCH_REGISTER_0 0xED
|
||||
#define DC_D_WINBUF_DD_SCRATCH_REGISTER_1 0xEE
|
||||
#define DC_T_WINBUF_TD_SCRATCH_REGISTER_0 0x16D
|
||||
#define DC_T_WINBUF_TD_SCRATCH_REGISTER_1 0x16E
|
||||
#define DC_COM_SCRATCH_REGISTER_A 0x325
|
||||
#define DC_COM_SCRATCH_REGISTER_B 0x326
|
||||
#define DC_A_WINBUF_AD_SCRATCH_REGISTER_0 0xBED
|
||||
#define DC_A_WINBUF_AD_SCRATCH_REGISTER_1 0xBEE
|
||||
#define DC_B_WINBUF_BD_SCRATCH_REGISTER_0 0xDED
|
||||
#define DC_B_WINBUF_BD_SCRATCH_REGISTER_1 0xDEE
|
||||
#define DC_C_WINBUF_CD_SCRATCH_REGISTER_0 0xFED
|
||||
#define DC_C_WINBUF_CD_SCRATCH_REGISTER_1 0xFEE
|
||||
|
||||
// DC_CMD non-shadowed command/sync registers.
|
||||
#define DC_CMD_GENERAL_INCR_SYNCPT 0x00
|
||||
|
||||
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01
|
||||
@@ -50,6 +65,7 @@
|
||||
#define PM0_ENABLE (1 << 16)
|
||||
#define PM1_ENABLE (1 << 18)
|
||||
|
||||
#define DC_CMD_INT_STATUS 0x37
|
||||
#define DC_CMD_INT_MASK 0x38
|
||||
#define DC_CMD_INT_ENABLE 0x39
|
||||
|
||||
@@ -62,11 +78,13 @@
|
||||
#define WIN_A_ACT_REQ (1 << 1)
|
||||
#define WIN_B_ACT_REQ (1 << 2)
|
||||
#define WIN_C_ACT_REQ (1 << 3)
|
||||
#define WIN_D_ACT_REQ (1 << 4)
|
||||
#define CURSOR_ACT_REQ (1 << 7)
|
||||
#define GENERAL_UPDATE (1 << 8)
|
||||
#define WIN_A_UPDATE (1 << 9)
|
||||
#define WIN_B_UPDATE (1 << 10)
|
||||
#define WIN_C_UPDATE (1 << 11)
|
||||
#define WIN_D_UPDATE (1 << 12)
|
||||
#define CURSOR_UPDATE (1 << 15)
|
||||
#define NC_HOST_TRIG (1 << 24)
|
||||
|
||||
@@ -74,15 +92,38 @@
|
||||
#define WINDOW_A_SELECT (1 << 4)
|
||||
#define WINDOW_B_SELECT (1 << 5)
|
||||
#define WINDOW_C_SELECT (1 << 6)
|
||||
#define WINDOW_D_SELECT (1 << 7)
|
||||
|
||||
#define DC_CMD_REG_ACT_CONTROL 0x043
|
||||
|
||||
// DC_D_WIN_DD window D instance of DC_WIN
|
||||
#define DC_D_WIN_DD_WIN_OPTIONS 0x80
|
||||
#define DC_D_WIN_DD_COLOR_DEPTH 0x83
|
||||
#define DC_D_WIN_DD_POSITION 0x84
|
||||
#define DC_D_WIN_DD_SIZE 0x85
|
||||
#define DC_D_WIN_DD_LINE_STRIDE 0x8A
|
||||
#define DC_D_WIN_DD_BLEND_LAYER_CONTROL 0x96
|
||||
#define DC_D_WIN_DD_BLEND_MATCH_SELECT 0x97
|
||||
#define DC_D_WIN_DD_BLEND_ALPHA_1BIT 0x99
|
||||
|
||||
// DC_D_WINBUF_DD window D instance of DC_WINBUF
|
||||
#define DC_D_WINBUF_DD_START_ADDR 0xC0
|
||||
#define DC_D_WINBUF_DD_ADDR_H_OFFSET 0xC6
|
||||
#define DC_D_WINBUF_DD_ADDR_V_OFFSET 0xC8
|
||||
#define DC_D_WINBUF_DD_START_ADDR_HI 0xCD
|
||||
#define DC_D_WINBUF_DD_MEMFETCH_CONTROL 0xEB
|
||||
|
||||
// DC_T_WIN_TD macro for using DD defines.
|
||||
#define _DC_T(reg) ((reg) + 0x80)
|
||||
|
||||
// DC_COM non-shadowed registers.
|
||||
#define DC_COM_CRC_CONTROL 0x300
|
||||
#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
|
||||
#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
|
||||
|
||||
#define DC_COM_DSC_TOP_CTL 0x33E
|
||||
|
||||
// DC_DISP shadowed registers.
|
||||
#define DC_DISP_DISP_WIN_OPTIONS 0x402
|
||||
#define HDMI_ENABLE (1 << 30)
|
||||
#define DSI_ENABLE (1 << 29)
|
||||
@@ -161,6 +202,32 @@
|
||||
#define DE_CONTROL_EARLY (3 << 2)
|
||||
#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
|
||||
|
||||
// Cursor configuration registers.
|
||||
#define DC_DISP_CURSOR_FOREGROUND 0x43C
|
||||
#define DC_DISP_CURSOR_BACKGROUND 0x43D
|
||||
#define CURSOR_COLOR(r,g,b) (((r) & 0xFF) | (((g) & 0xFF) << 8) | (((b) & 0xFF) << 16))
|
||||
|
||||
#define DC_DISP_CURSOR_START_ADDR 0x43E
|
||||
#define CURSOR_CLIPPING(w) ((w) << 28)
|
||||
#define CURSOR_CLIP_WIN_A 1
|
||||
#define CURSOR_CLIP_WIN_B 2
|
||||
#define CURSOR_CLIP_WIN_C 3
|
||||
#define CURSOR_SIZE_32 (0 << 24)
|
||||
#define CURSOR_SIZE_64 (1 << 24)
|
||||
#define CURSOR_SIZE_128 (2 << 24)
|
||||
#define CURSOR_SIZE_256 (3 << 24)
|
||||
#define DC_DISP_CURSOR_POSITION 0x440
|
||||
#define DC_DISP_CURSOR_START_ADDR_HI 0x4EC
|
||||
#define DC_DISP_BLEND_CURSOR_CONTROL 0x4F1
|
||||
#define CURSOR_BLEND_2BIT (0 << 24)
|
||||
#define CURSOR_BLEND_R8G8B8A8 (1 << 24)
|
||||
#define CURSOR_BLEND_SRC_FACTOR(n) ((n) << 8)
|
||||
#define CURSOR_BLEND_DST_FACTOR(n) ((n) << 16)
|
||||
#define CURSOR_BLEND_ZRO 0
|
||||
#define CURSOR_BLEND_K1 1
|
||||
#define CURSOR_BLEND_NK1 2
|
||||
// End of cursor cfg regs.
|
||||
|
||||
#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
|
||||
#define DC_DISP_SD_BL_PARAMETERS 0x4D7
|
||||
#define DC_DISP_SD_BL_CONTROL 0x4DC
|
||||
@@ -187,6 +254,13 @@
|
||||
#define CSC_ENABLE (1 << 18)
|
||||
#define WIN_ENABLE (1 << 30)
|
||||
|
||||
#define DC_WIN_BUFFER_CONTROL 0x702
|
||||
#define BUFFER_CONTROL_HOST 0
|
||||
#define BUFFER_CONTROL_VI 1
|
||||
#define BUFFER_CONTROL_EPP 2
|
||||
#define BUFFER_CONTROL_MPEGE 3
|
||||
#define BUFFER_CONTROL_SB2D 4
|
||||
|
||||
#define DC_WIN_COLOR_DEPTH 0x703
|
||||
#define WIN_COLOR_DEPTH_P1 0x0
|
||||
#define WIN_COLOR_DEPTH_P2 0x1
|
||||
@@ -211,8 +285,9 @@
|
||||
#define WIN_COLOR_DEPTH_YCbCr422RA 0x18
|
||||
#define WIN_COLOR_DEPTH_YUV422RA 0x19
|
||||
|
||||
#define DC_WIN_BUFFER_CONTROL 0x702
|
||||
#define DC_WIN_POSITION 0x704
|
||||
#define H_POSITION(x) (((x) & 0xFfff) << 0)
|
||||
#define V_POSITION(x) (((x) & 0x1fff) << 16)
|
||||
|
||||
#define DC_WIN_SIZE 0x705
|
||||
#define H_SIZE(x) (((x) & 0x1fff) << 0)
|
||||
@@ -234,6 +309,42 @@
|
||||
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
|
||||
#define DC_WIN_DV_CONTROL 0x70E
|
||||
|
||||
#define DC_WINBUF_BLEND_LAYER_CONTROL 0x716
|
||||
#define WIN_K1(x) (((x) & 0xff) << 8)
|
||||
#define WIN_K2(x) (((x) & 0xff) << 16)
|
||||
#define WIN_BLEND_ENABLE (0 << 24)
|
||||
#define WIN_BLEND_BYPASS (1 << 24)
|
||||
|
||||
#define DC_WINBUF_BLEND_MATCH_SELECT 0x717
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ZERO (0 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ONE (1 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 (2 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_DST (3 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_NEG_K1_TIMES_DST (4 << 0)
|
||||
#define WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_SRC (5 << 0)
|
||||
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ZERO (0 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ONE (1 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1 (2 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K2 (3 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1_TIMES_DST (4 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_DST (5 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_SRC (6 << 4)
|
||||
#define WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1 (7 << 4)
|
||||
|
||||
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_ZERO (0 << 8)
|
||||
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K1 (1 << 8)
|
||||
#define WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K2 (2 << 8)
|
||||
|
||||
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ZERO (0 << 12)
|
||||
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ONE (1 << 12)
|
||||
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_NEG_K1_TIMES_SRC (2 << 12)
|
||||
#define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_K2 (3 << 12)
|
||||
|
||||
#define DC_WINBUF_BLEND_ALPHA_1BIT 0x719
|
||||
#define WIN_ALPHA_1BIT_WEIGHT0(x) (((x) & 0xff) << 0)
|
||||
#define WIN_ALPHA_1BIT_WEIGHT1(x) (((x) & 0xff) << 8)
|
||||
|
||||
/*! The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
|
||||
#define DC_WINBUF_START_ADDR 0x800
|
||||
#define DC_WINBUF_ADDR_H_OFFSET 0x806
|
||||
@@ -336,6 +447,7 @@
|
||||
|
||||
#define DSI_PAD_CONTROL_CD 0x4C
|
||||
#define DSI_VIDEO_MODE_CONTROL 0x4E
|
||||
#define DSI_CMD_PKT_VID_ENABLE 1
|
||||
|
||||
#define DSI_PAD_CONTROL_1 0x4F
|
||||
#define DSI_PAD_CONTROL_2 0x50
|
||||
@@ -349,7 +461,59 @@
|
||||
#define DSI_PAD_CONTROL_4 0x52
|
||||
#define DSI_INIT_SEQ_DATA_15 0x5F
|
||||
|
||||
#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 0x60
|
||||
/*! MIPI registers. */
|
||||
#define MIPI_CAL_MIPI_CAL_CTRL (0x00 / 0x4)
|
||||
#define MIPI_CAL_CIL_MIPI_CAL_STATUS (0x08 / 0x4)
|
||||
#define MIPI_CAL_CILA_MIPI_CAL_CONFIG (0x14 / 0x4)
|
||||
#define MIPI_CAL_CILB_MIPI_CAL_CONFIG (0x18 / 0x4)
|
||||
#define MIPI_CAL_CILC_MIPI_CAL_CONFIG (0x1C / 0x4)
|
||||
#define MIPI_CAL_CILD_MIPI_CAL_CONFIG (0x20 / 0x4)
|
||||
#define MIPI_CAL_CILE_MIPI_CAL_CONFIG (0x24 / 0x4)
|
||||
#define MIPI_CAL_CILF_MIPI_CAL_CONFIG (0x28 / 0x4)
|
||||
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG (0x38 / 0x4)
|
||||
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG (0x3C / 0x4)
|
||||
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG (0x40 / 0x4)
|
||||
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG (0x44 / 0x4)
|
||||
#define MIPI_CAL_MIPI_BIAS_PAD_CFG0 (0x58 / 0x4)
|
||||
#define MIPI_CAL_MIPI_BIAS_PAD_CFG1 (0x5C / 0x4)
|
||||
#define MIPI_CAL_MIPI_BIAS_PAD_CFG2 (0x60 / 0x4)
|
||||
#define MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2 (0x64 / 0x4)
|
||||
#define MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2 (0x68 / 0x4)
|
||||
#define MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2 (0x70 / 0x4)
|
||||
#define MIPI_CAL_DSID_MIPI_CAL_CONFIG_2 (0x74 / 0x4)
|
||||
|
||||
/*! MIPI CMDs. */
|
||||
#define MIPI_DSI_DCS_SHORT_WRITE 0x05
|
||||
#define MIPI_DSI_DCS_READ 0x06
|
||||
#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15
|
||||
#define MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE 0x37
|
||||
#define MIPI_DSI_DCS_LONG_WRITE 0x39
|
||||
|
||||
/*! MIPI DCS CMDs. */
|
||||
#define MIPI_DCS_GET_DISPLAY_ID 0x04
|
||||
#define MIPI_DCS_ENTER_SLEEP_MODE 0x10
|
||||
#define MIPI_DCS_EXIT_SLEEP_MODE 0x11
|
||||
#define MIPI_DCS_SET_DISPLAY_ON 0x29
|
||||
|
||||
/* Switch Panels:
|
||||
* [10] 81 [26]: JDI LPM062M326A
|
||||
* [10] 96 [09]: JDI LAM062M109A
|
||||
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
|
||||
* [20] XX [10]: InnoLux P062CCA-AZ2 [UNCONFIRMED ID]
|
||||
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
|
||||
* [30] XX [10]: AUO A062TAN02 (59.06A33.002) [UNCONFIRMED ID]
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
PANEL_JDI_LPM062M = 0x10,
|
||||
PANEL_JDI_LAM062M109A = 0x0910,
|
||||
PANEL_JDI_LPM062M326A = 0x2610,
|
||||
PANEL_INL_P062CCA_AZ1 = 0x0F20,
|
||||
PANEL_AUO_A062TAN01 = 0x0F30,
|
||||
PANEL_INL_P062CCA_AZ2 = 0x1020,
|
||||
PANEL_AUO_A062TAN02 = 0x1030
|
||||
};
|
||||
|
||||
void display_init();
|
||||
void display_backlight_pwm_init();
|
||||
@@ -363,7 +527,13 @@ void display_backlight(bool enable);
|
||||
void display_backlight_brightness(u32 brightness, u32 step_delay);
|
||||
|
||||
/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */
|
||||
u32 *display_init_framebuffer();
|
||||
u32 *display_init_framebuffer2();
|
||||
u32 *display_init_framebuffer_pitch();
|
||||
u32 *display_init_framebuffer_block();
|
||||
u32 *display_init_framebuffer_log();
|
||||
void display_activate_console();
|
||||
void display_deactivate_console();
|
||||
void display_init_cursor(void *crs_fb, u32 size);
|
||||
void display_set_pos_cursor(u32 x, u32 y);
|
||||
void display_deinit_cursor();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-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,
|
||||
@@ -15,16 +15,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//Clock config.
|
||||
static const cfg_op_t _display_config_1[4] = {
|
||||
{0x4E, 0x40000000}, //CLK_RST_CONTROLLER_CLK_SOURCE_DISP1
|
||||
{0x34, 0x4830A001}, //CLK_RST_CONTROLLER_PLLD_BASE
|
||||
{0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1
|
||||
{0x37, 0x2D0AAA} //CLK_RST_CONTROLLER_PLLD_MISC
|
||||
};
|
||||
|
||||
//Display A config.
|
||||
static const cfg_op_t _display_config_2[94] = {
|
||||
static const cfg_op_t _display_dc_setup_win_config[94] = {
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ},
|
||||
@@ -128,7 +120,7 @@ static const cfg_op_t _display_config_2[94] = {
|
||||
};
|
||||
|
||||
//DSI Init config.
|
||||
static const cfg_op_t _display_config_3[61] = {
|
||||
static const cfg_op_t _display_dsi_init_config[61] = {
|
||||
{DSI_WR_DATA, 0},
|
||||
{DSI_INT_ENABLE, 0},
|
||||
{DSI_INT_STATUS, 0},
|
||||
@@ -192,14 +184,14 @@ static const cfg_op_t _display_config_3[61] = {
|
||||
{DSI_INIT_SEQ_CONTROL, 0}
|
||||
};
|
||||
|
||||
//DSI config (if ver == 0x10).
|
||||
static const cfg_op_t _display_config_4[43] = {
|
||||
{DSI_WR_DATA, 0x439},
|
||||
{DSI_WR_DATA, 0x9483FFB9},
|
||||
//DSI panel config.
|
||||
static const cfg_op_t _display_init_config_jdi[43] = {
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xBD15},
|
||||
{DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x0BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x1939},
|
||||
{DSI_WR_DATA, 0x1939}, // MIPI_DSI_DCS_LONG_WRITE: 25 bytes.
|
||||
{DSI_WR_DATA, 0xAAAAAAD8},
|
||||
{DSI_WR_DATA, 0xAAAAAAEB},
|
||||
{DSI_WR_DATA, 0xAAEBAAAA},
|
||||
@@ -208,9 +200,9 @@ static const cfg_op_t _display_config_4[43] = {
|
||||
{DSI_WR_DATA, 0xAAEBAAAA},
|
||||
{DSI_WR_DATA, 0xAA},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x1BD15},
|
||||
{DSI_WR_DATA, 0x01BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x1BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2739},
|
||||
{DSI_WR_DATA, 0x2739}, // MIPI_DSI_DCS_LONG_WRITE: 39 bytes.
|
||||
{DSI_WR_DATA, 0xFFFFFFD8},
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
@@ -222,25 +214,25 @@ static const cfg_op_t _display_config_4[43] = {
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
{DSI_WR_DATA, 0xFFFFFF},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2BD15},
|
||||
{DSI_WR_DATA, 0x02BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x2BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xF39},
|
||||
{DSI_WR_DATA, 0xF39}, // MIPI_DSI_DCS_LONG_WRITE: 15 bytes.
|
||||
{DSI_WR_DATA, 0xFFFFFFD8},
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
{DSI_WR_DATA, 0xFFFFFFFF},
|
||||
{DSI_WR_DATA, 0xFFFFFF},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xBD15},
|
||||
{DSI_WR_DATA, 0x00BD15}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x0BD.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x6D915},
|
||||
{DSI_WR_DATA, 0x06D915}, // MIPI_DSI_DCS_SHORT_WRITE_PARAM: 0x6D9.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x439},
|
||||
{DSI_WR_DATA, 0xB9},
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x000000B9}, // Disable extension cmd.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST}
|
||||
};
|
||||
|
||||
//DSI config.
|
||||
static const cfg_op_t _display_config_5[21] = {
|
||||
//DSI packet config.
|
||||
static const cfg_op_t _display_dsi_packet_config[21] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PHY_TIMING_0, 0x6070601},
|
||||
{DSI_PHY_TIMING_1, 0x40A0E05},
|
||||
@@ -264,15 +256,8 @@ static const cfg_op_t _display_config_5[21] = {
|
||||
{DSI_HOST_CONTROL, 0},
|
||||
};
|
||||
|
||||
//Clock config.
|
||||
static const cfg_op_t _display_config_6[3] = {
|
||||
{0x34, 0x4810C001}, //CLK_RST_CONTROLLER_PLLD_BASE
|
||||
{0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1
|
||||
{0x37, 0x2DFC00} //CLK_RST_CONTROLLER_PLLD_MISC
|
||||
};
|
||||
|
||||
//DSI config.
|
||||
static const cfg_op_t _display_config_7[10] = {
|
||||
//DSI mode config.
|
||||
static const cfg_op_t _display_dsi_mode_config[10] = {
|
||||
{DSI_TRIGGER, 0},
|
||||
{DSI_CONTROL, 0},
|
||||
{DSI_SOL_DELAY, 6},
|
||||
@@ -286,17 +271,17 @@ static const cfg_op_t _display_config_7[10] = {
|
||||
};
|
||||
|
||||
//MIPI CAL config.
|
||||
static const cfg_op_t _display_config_8[6] = {
|
||||
{0x18, 0}, // MIPI_CAL_MIPI_BIAS_PAD_CFG2
|
||||
{0x02, 0xF3F10000}, // MIPI_CAL_CIL_MIPI_CAL_STATUS
|
||||
{0x16, 0}, // MIPI_CAL_MIPI_BIAS_PAD_CFG0
|
||||
{0x18, 0}, // MIPI_CAL_MIPI_BIAS_PAD_CFG2
|
||||
{0x18, 0x10010}, // MIPI_CAL_MIPI_BIAS_PAD_CFG2
|
||||
{0x17, 0x300} // MIPI_CAL_MIPI_BIAS_PAD_CFG1
|
||||
static const cfg_op_t _display_mipi_pad_cal_config[6] = {
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
|
||||
{MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0x10010},
|
||||
{MIPI_CAL_MIPI_BIAS_PAD_CFG1, 0x300}
|
||||
};
|
||||
|
||||
//DSI config.
|
||||
static const cfg_op_t _display_config_9[4] = {
|
||||
static const cfg_op_t _display_dsi_pad_cal_config[4] = {
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PAD_CONTROL_2, 0},
|
||||
{DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)},
|
||||
@@ -304,27 +289,27 @@ static const cfg_op_t _display_config_9[4] = {
|
||||
};
|
||||
|
||||
//MIPI CAL config.
|
||||
static const cfg_op_t _display_config_10[16] = {
|
||||
{0x0E, 0x200200}, // MIPI_CAL_DSIA_MIPI_CAL_CONFIG
|
||||
{0x0F, 0x200200}, // MIPI_CAL_DSIB_MIPI_CAL_CONFIG
|
||||
{0x19, 0x200002}, // MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2
|
||||
{0x1A, 0x200002}, // MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2
|
||||
{0x05, 0}, // MIPI_CAL_CILA_MIPI_CAL_CONFIG
|
||||
{0x06, 0}, // MIPI_CAL_CILB_MIPI_CAL_CONFIG
|
||||
{0x07, 0}, // MIPI_CAL_CILC_MIPI_CAL_CONFIG
|
||||
{0x08, 0}, // MIPI_CAL_CILD_MIPI_CAL_CONFIG
|
||||
{0x09, 0}, // MIPI_CAL_CILE_MIPI_CAL_CONFIG
|
||||
{0x0A, 0}, // MIPI_CAL_CILF_MIPI_CAL_CONFIG
|
||||
{0x10, 0}, // MIPI_CAL_DSIC_MIPI_CAL_CONFIG
|
||||
{0x11, 0}, // MIPI_CAL_DSID_MIPI_CAL_CONFIG
|
||||
{0x1A, 0}, // MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2
|
||||
{0x1C, 0}, // MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2
|
||||
{0x1D, 0}, // MIPI_CAL_DSID_MIPI_CAL_CONFIG_2
|
||||
{0, 0x2A000001} // MIPI_CAL_DSIA_MIPI_CAL_CONFIG
|
||||
static const cfg_op_t _display_mipi_apply_dsi_cal_config[16] = {
|
||||
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200},
|
||||
{MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002},
|
||||
{MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILD_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILE_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_CILF_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_DSID_MIPI_CAL_CONFIG, 0},
|
||||
{MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0},
|
||||
{MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0},
|
||||
{MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0},
|
||||
{MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001}
|
||||
};
|
||||
|
||||
//Display A config.
|
||||
static const cfg_op_t _display_config_11[113] = {
|
||||
static const cfg_op_t _display_video_disp_controller_enable_config[113] = {
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
@@ -449,7 +434,7 @@ static const cfg_op_t _display_config_11[113] = {
|
||||
};
|
||||
|
||||
////Display A config.
|
||||
static const cfg_op_t _display_config_12[17] = {
|
||||
static const cfg_op_t _display_video_disp_controller_disable_config[17] = {
|
||||
{DC_DISP_FRONT_PORCH, 0xA0088},
|
||||
{DC_CMD_INT_MASK, 0},
|
||||
{DC_CMD_STATE_ACCESS, 0},
|
||||
@@ -470,7 +455,7 @@ static const cfg_op_t _display_config_12[17] = {
|
||||
};
|
||||
|
||||
//DSI config.
|
||||
static const cfg_op_t _display_config_13[16] = {
|
||||
static const cfg_op_t _display_dsi_timing_deinit_config[16] = {
|
||||
{DSI_POWER_CONTROL, 0},
|
||||
{DSI_PAD_CONTROL_1, 0},
|
||||
{DSI_PHY_TIMING_0, 0x6070601},
|
||||
@@ -490,11 +475,11 @@ static const cfg_op_t _display_config_13[16] = {
|
||||
};
|
||||
|
||||
//DSI config (if ver == 0x10).
|
||||
static const cfg_op_t _display_config_14[22] = {
|
||||
{DSI_WR_DATA, 0x439},
|
||||
{DSI_WR_DATA, 0x9483FFB9},
|
||||
static const cfg_op_t _display_deinit_config_jdi[22] = {
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2139},
|
||||
{DSI_WR_DATA, 0x2139}, // MIPI_DSI_DCS_LONG_WRITE: 33 bytes.
|
||||
{DSI_WR_DATA, 0x191919D5},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
@@ -505,95 +490,171 @@ static const cfg_op_t _display_config_14[22] = {
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xB39},
|
||||
{DSI_WR_DATA, 0x4F0F41B1},
|
||||
{DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
|
||||
{DSI_WR_DATA, 0x4F0F41B1}, // Set Power control.
|
||||
{DSI_WR_DATA, 0xF179A433},
|
||||
{DSI_WR_DATA, 0x2D81},
|
||||
{DSI_WR_DATA, 0x002D81},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x439},
|
||||
{DSI_WR_DATA, 0xB9},
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x000000B9}, // Disable extension cmd.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST}
|
||||
};
|
||||
|
||||
static const cfg_op_t _display_deinit_config_auo[37] = {
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x9483FFB9}, // Enable extension cmd. (Pass: FF 83 94).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes.
|
||||
{DSI_WR_DATA, 0x191919D5},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x2C39}, // MIPI_DSI_DCS_LONG_WRITE: 44 bytes.
|
||||
{DSI_WR_DATA, 0x191919D6},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_WR_DATA, 0x19191919},
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0xB39}, // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
|
||||
{DSI_WR_DATA, 0x711148B1}, // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
|
||||
// Set Power control. (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/32, Enter standby / PON / VCOMG).
|
||||
{DSI_WR_DATA, 0x71143209},
|
||||
{DSI_WR_DATA, 0x114D31}, // Set Power control. (Unknown).
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
{DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
|
||||
{DSI_WR_DATA, 0x000000B9}, // Disable extension cmd.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST}
|
||||
};
|
||||
|
||||
static const cfg_op_t _display_init_config_invert[3] = {
|
||||
{DSI_WR_DATA, 0x239},
|
||||
{DSI_WR_DATA, 0x02C1}, // INV_EN.
|
||||
{DSI_TRIGGER, DSI_TRIGGER_HOST},
|
||||
};
|
||||
|
||||
//Display A config.
|
||||
static const cfg_op_t cfg_display_one_color[8] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} //DISPLAY_CTRL_MODE: continuous display.
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display.
|
||||
};
|
||||
|
||||
//Display A config.
|
||||
static const cfg_op_t cfg_display_framebuffer[32] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C.
|
||||
//Display A config pitch.
|
||||
static const cfg_op_t cfg_display_framebuffer_pitch[34] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //T_A8R8G8B8 //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_POSITION, 0}, //(0,0)
|
||||
{DC_WIN_H_INITIAL_DDA, 0},
|
||||
{DC_WIN_V_INITIAL_DDA, 0},
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, //Pre-scaled size: 1280x2880 bytes.
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)},
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, //Window size: 1280 vertical lines x 720 horizontal pixels.
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, 0},
|
||||
{DC_WINBUF_SURFACE_KIND, 0}, //Regular surface.
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)},
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
|
||||
{DC_WINBUF_SURFACE_KIND, PITCH},
|
||||
{DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0}, //Linear: 0x383FFC, Block: 0x3813FC
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 1279}, //Linear: 1279, Block: 0
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0}, // Linear: 0x383FFC, Block: 0x3813FC.
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0.
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, // Enable window AD.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
static const cfg_op_t cfg_display_framebuffer2[32] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C.
|
||||
//Display A config block linear.
|
||||
static const cfg_op_t cfg_display_framebuffer_block[34] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A.
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //T_A8R8G8B8 //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8.
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_POSITION, 0}, //(0,0)
|
||||
{DC_WIN_H_INITIAL_DDA, 0},
|
||||
{DC_WIN_V_INITIAL_DDA, 0},
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, //Pre-scaled size: 1280x2880 bytes.
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)},
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, //Window size: 1280 vertical lines x 720 horizontal pixels.
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, 0},
|
||||
{DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK}, //Regular surface.
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)},
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)},
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
|
||||
{DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK},
|
||||
{DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address.
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, //Linear: 0x383FFC, Block: 0x3813FC
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 0}, //Linear: 1279, Block: 0
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, // Linear: 0x383FFC, Block: 0x3813FC.
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0.
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | SCAN_COLUMN | H_DIRECTION}, //Enable window AD. | SCAN_COLUMN | H_DIRECTION
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request.
|
||||
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE},
|
||||
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | SCAN_COLUMN | H_DIRECTION}, // Enable window AD. | SCAN_COLUMN | H_DIRECTION.
|
||||
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ}
|
||||
};
|
||||
|
||||
//Display D config.
|
||||
static const cfg_op_t cfg_display_framebuffer_log[20] = {
|
||||
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT},
|
||||
{DC_WIN_WIN_OPTIONS, 0},
|
||||
{DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8},
|
||||
{DC_WIN_POSITION, 0}, //(0,0)
|
||||
{DC_WIN_H_INITIAL_DDA, 0},
|
||||
{DC_WIN_V_INITIAL_DDA, 0},
|
||||
{DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(656 * 4)},
|
||||
{DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x.
|
||||
{DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(656)},
|
||||
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(656 * 2) | LINE_STRIDE(656 * 4)}, //656*2x656*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
|
||||
{DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST},
|
||||
{DC_WINBUF_SURFACE_KIND, PITCH},
|
||||
{DC_WINBUF_START_ADDR, LOG_FB_ADDRESS}, // Framebuffer address.
|
||||
{DC_WINBUF_ADDR_H_OFFSET, 0},
|
||||
{DC_WINBUF_ADDR_V_OFFSET, 0},
|
||||
{DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_ENABLE | WIN_K1(200)},
|
||||
{DC_WINBUF_BLEND_MATCH_SELECT, WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 | WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1},
|
||||
{DC_WIN_WIN_OPTIONS, 0}, // Enable window DD.
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE},
|
||||
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_D_ACT_REQ}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2020 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,
|
||||
@@ -117,14 +117,6 @@ static const u8 _gfx_font[] = {
|
||||
0x00, 0x00, 0x00, 0x4C, 0x32, 0x00, 0x00, 0x00 // Char 126 (~)
|
||||
};
|
||||
|
||||
void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride)
|
||||
{
|
||||
gfx_ctxt.fb = fb;
|
||||
gfx_ctxt.width = width;
|
||||
gfx_ctxt.height = height;
|
||||
gfx_ctxt.stride = stride;
|
||||
}
|
||||
|
||||
void gfx_clear_grey(u8 color)
|
||||
{
|
||||
memset(gfx_ctxt.fb, color, gfx_ctxt.width * gfx_ctxt.height * 4);
|
||||
@@ -136,9 +128,14 @@ void gfx_clear_color(u32 color)
|
||||
gfx_ctxt.fb[i] = color;
|
||||
}
|
||||
|
||||
void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height)
|
||||
void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride)
|
||||
{
|
||||
memset(gfx_ctxt.fb + pos_x * gfx_ctxt.stride, color, height * 4 * gfx_ctxt.stride);
|
||||
gfx_ctxt.fb = fb;
|
||||
gfx_ctxt.width = width;
|
||||
gfx_ctxt.height = height;
|
||||
gfx_ctxt.stride = stride;
|
||||
|
||||
gfx_clear_grey(0);
|
||||
}
|
||||
|
||||
void gfx_con_init()
|
||||
@@ -149,9 +146,9 @@ void gfx_con_init()
|
||||
gfx_con.y = 0;
|
||||
gfx_con.savedx = 0;
|
||||
gfx_con.savedy = 0;
|
||||
gfx_con.fgcol = 0xFFCCCCCC;
|
||||
gfx_con.fgcol = 0xFFFFFFFF;
|
||||
gfx_con.fillbg = 1;
|
||||
gfx_con.bgcol = 0xFF1B1B1B;
|
||||
gfx_con.bgcol = 0xFF000000;
|
||||
gfx_con.mute = 0;
|
||||
}
|
||||
|
||||
@@ -174,6 +171,7 @@ void gfx_con_setpos(u32 x, u32 y)
|
||||
gfx_con.y = y;
|
||||
}
|
||||
|
||||
static int gfx_column = 0;
|
||||
void gfx_putc(char c)
|
||||
{
|
||||
// Duplicate code for performance reasons.
|
||||
@@ -183,33 +181,23 @@ void gfx_putc(char c)
|
||||
if (c >= 32 && c <= 126)
|
||||
{
|
||||
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
|
||||
u32 *fb = gfx_ctxt.fb + gfx_con.x + gfx_con.y * gfx_ctxt.stride;
|
||||
|
||||
for (u32 i = 0; i < 16; i += 2)
|
||||
{
|
||||
u8 v = *cbuf;
|
||||
for (u32 k = 0; k < 2; k++)
|
||||
{
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
u32 fb_off = gfx_con.y + i + k + (gfx_ctxt.width - gfx_con.x) * gfx_ctxt.stride;
|
||||
for (u32 j = 0; j < 16; j += 2)
|
||||
{
|
||||
if (v & 1)
|
||||
for (u32 l = 0; l < 2; l++)
|
||||
{
|
||||
*fb = gfx_con.fgcol;
|
||||
fb++;
|
||||
*fb = gfx_con.fgcol;
|
||||
if (v & 1)
|
||||
gfx_ctxt.fb[fb_off - (j + l) * gfx_ctxt.stride] = gfx_con.fgcol;
|
||||
else if (gfx_con.fillbg)
|
||||
gfx_ctxt.fb[fb_off - (j + l) * gfx_ctxt.stride] = gfx_con.bgcol;
|
||||
}
|
||||
else if (gfx_con.fillbg)
|
||||
{
|
||||
*fb = gfx_con.bgcol;
|
||||
fb++;
|
||||
*fb = gfx_con.bgcol;
|
||||
}
|
||||
else
|
||||
fb++;
|
||||
v >>= 1;
|
||||
fb++;
|
||||
}
|
||||
fb += gfx_ctxt.stride - 16;
|
||||
v = *cbuf;
|
||||
}
|
||||
cbuf++;
|
||||
@@ -218,10 +206,18 @@ void gfx_putc(char c)
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
gfx_con.x = 0;
|
||||
gfx_con.x = gfx_column;
|
||||
gfx_con.y +=16;
|
||||
if (gfx_con.y > gfx_ctxt.height - 16)
|
||||
if (gfx_con.y > gfx_ctxt.height - 33)
|
||||
{
|
||||
gfx_con.y = 0;
|
||||
|
||||
if (!gfx_column)
|
||||
gfx_column = 640;
|
||||
else
|
||||
gfx_column = 0;
|
||||
gfx_con.x = gfx_column;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
@@ -229,35 +225,41 @@ void gfx_putc(char c)
|
||||
if (c >= 32 && c <= 126)
|
||||
{
|
||||
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
|
||||
u32 *fb = gfx_ctxt.fb + gfx_con.x + gfx_con.y * gfx_ctxt.stride;
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
u8 v = *cbuf++;
|
||||
u32 fb_off = gfx_con.y + i + (gfx_ctxt.width - gfx_con.x) * gfx_ctxt.stride;
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
{
|
||||
if (v & 1)
|
||||
*fb = gfx_con.fgcol;
|
||||
gfx_ctxt.fb[fb_off - (j * gfx_ctxt.stride)] = gfx_con.fgcol;
|
||||
else if (gfx_con.fillbg)
|
||||
*fb = gfx_con.bgcol;
|
||||
gfx_ctxt.fb[fb_off - (j * gfx_ctxt.stride)] = gfx_con.bgcol;
|
||||
v >>= 1;
|
||||
fb++;
|
||||
}
|
||||
fb += gfx_ctxt.stride - 8;
|
||||
}
|
||||
gfx_con.x += 8;
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
gfx_con.x = 0;
|
||||
gfx_con.x = gfx_column;
|
||||
gfx_con.y += 8;
|
||||
if (gfx_con.y > gfx_ctxt.height - 8)
|
||||
if (gfx_con.y > gfx_ctxt.height - 33)
|
||||
{
|
||||
gfx_con.y = 0;
|
||||
|
||||
if (!gfx_column)
|
||||
gfx_column = 640;
|
||||
else
|
||||
gfx_column = 0;
|
||||
gfx_con.x = gfx_column;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_puts(const char *s)
|
||||
void gfx_puts(char *s)
|
||||
{
|
||||
if (!s || gfx_con.mute)
|
||||
return;
|
||||
@@ -297,22 +299,6 @@ static void _gfx_putn(u32 v, int base, char fill, int fcnt)
|
||||
gfx_puts(p);
|
||||
}
|
||||
|
||||
void gfx_put_small_sep()
|
||||
{
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
gfx_con.fntsz = 8;
|
||||
gfx_putc('\n');
|
||||
gfx_con.fntsz = prevFontSize;
|
||||
}
|
||||
|
||||
void gfx_put_big_sep()
|
||||
{
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
gfx_con.fntsz = 16;
|
||||
gfx_putc('\n');
|
||||
gfx_con.fntsz = prevFontSize;
|
||||
}
|
||||
|
||||
void gfx_printf(const char *fmt, ...)
|
||||
{
|
||||
if (gfx_con.mute)
|
||||
@@ -442,108 +428,12 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
gfx_con.fntsz = prevFontSize;
|
||||
}
|
||||
|
||||
static int abs(int x)
|
||||
{
|
||||
if (x < 0)
|
||||
return -x;
|
||||
return x;
|
||||
}
|
||||
|
||||
void gfx_set_pixel(u32 x, u32 y, u32 color)
|
||||
{
|
||||
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = color;
|
||||
gfx_ctxt.fb[y + (gfx_ctxt.width - x) * gfx_ctxt.stride] = color;
|
||||
}
|
||||
|
||||
void gfx_line(int x0, int y0, int x1, int y1, u32 color)
|
||||
{
|
||||
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
||||
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
||||
int err = (dx > dy ? dx : -dy) / 2, e2;
|
||||
|
||||
while (1)
|
||||
{
|
||||
gfx_set_pixel(x0, y0, color);
|
||||
if (x0 == x1 && y0 == y1)
|
||||
break;
|
||||
e2 = err;
|
||||
if (e2 >-dx)
|
||||
{
|
||||
err -= dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 < dy)
|
||||
{
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_set_rect_grey(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
u32 pos = 0;
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
{
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
{
|
||||
memset(&gfx_ctxt.fb[x + y*gfx_ctxt.stride], buf[pos], 4);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gfx_set_rect_rgb(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
u32 pos = 0;
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
{
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
{
|
||||
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = buf[pos + 2] | (buf[pos + 1] << 8) | (buf[pos] << 16);
|
||||
pos+=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
u32 *ptr = (u32 *)buf;
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = *ptr++;
|
||||
}
|
||||
|
||||
void gfx_set_rect_argb_land(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
u32 pos = 0;
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
{
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
{
|
||||
gfx_ctxt.fb[y + (gfx_ctxt.width - x) * gfx_ctxt.stride] = buf[pos];
|
||||
pos+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_fill_rect_argb(const u32 color, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = color;
|
||||
}
|
||||
|
||||
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
|
||||
{
|
||||
for (u32 y = pos_y; y < (pos_y + size_y); y++)
|
||||
{
|
||||
for (u32 x = pos_x; x < (pos_x + size_x); x++)
|
||||
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = buf[(size_y + pos_y - 1 - y ) * size_x + x - pos_x];
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((target("arm"))) void gfx_set_rect_land_pitch(u32 *fb, const u32 *buf, u32 pos_x, u32 pos_y, u32 pos_x2, u32 pos_y2)
|
||||
void __attribute__((optimize("unroll-loops"))) gfx_set_rect_land_pitch(u32 *fb, const u32 *buf, u32 stride, u32 pos_x, u32 pos_y, u32 pos_x2, u32 pos_y2)
|
||||
{
|
||||
u32 *ptr = (u32 *)buf;
|
||||
|
||||
@@ -554,27 +444,27 @@ __attribute__((target("arm"))) void gfx_set_rect_land_pitch(u32 *fb, const u32 *
|
||||
for (u32 y = pos_y; y < (pos_y2 + 1); y++)
|
||||
for (u32 x = pos_x; x < (pos_x2 + 1); x+=8)
|
||||
{
|
||||
u32 *fbx = &fb[x * gfx_ctxt.stride + y];
|
||||
u32 *fbx = &fb[x * stride + y];
|
||||
|
||||
fbx[0] = *ptr++;
|
||||
fbx[gfx_ctxt.stride] = *ptr++;
|
||||
fbx[gfx_ctxt.stride * 2] = *ptr++;
|
||||
fbx[gfx_ctxt.stride * 3] = *ptr++;
|
||||
fbx[gfx_ctxt.stride * 4] = *ptr++;
|
||||
fbx[gfx_ctxt.stride * 5] = *ptr++;
|
||||
fbx[gfx_ctxt.stride * 6] = *ptr++;
|
||||
fbx[gfx_ctxt.stride * 7] = *ptr++;
|
||||
fbx[0] = *ptr++;
|
||||
fbx[stride] = *ptr++;
|
||||
fbx[stride * 2] = *ptr++;
|
||||
fbx[stride * 3] = *ptr++;
|
||||
fbx[stride * 4] = *ptr++;
|
||||
fbx[stride * 5] = *ptr++;
|
||||
fbx[stride * 6] = *ptr++;
|
||||
fbx[stride * 7] = *ptr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 y = pos_y; y < (pos_y2 + 1); y++)
|
||||
for (u32 x = pos_x; x < (pos_x2 + 1); x++)
|
||||
fb[x * gfx_ctxt.stride + y] = *ptr++;
|
||||
fb[x * stride + y] = *ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((target("arm"))) void gfx_set_rect_land_block(const u32 *buf, u32 pos_x, u32 pos_y, u32 pos_x2, u32 pos_y2)
|
||||
void __attribute__((optimize("unroll-loops"))) gfx_set_rect_land_block(u32 *fb, const u32 *buf, u32 pos_x, u32 pos_y, u32 pos_x2, u32 pos_y2)
|
||||
{
|
||||
u32 *ptr = (u32 *)buf;
|
||||
u32 GOB_address = 0;
|
||||
@@ -596,7 +486,7 @@ __attribute__((target("arm"))) void gfx_set_rect_land_block(const u32 *buf, u32
|
||||
+ (((x2 % 32) >> 4) << 5)
|
||||
+ ((y % 2) << 4) + (x2 % 16);
|
||||
|
||||
*(u32 *)(gfx_ctxt.fb + (addr >> 2)) = *ptr++;
|
||||
*(u32 *)(fb + (addr >> 2)) = *ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,31 +28,20 @@
|
||||
|
||||
void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride);
|
||||
void gfx_clear_grey(u8 color);
|
||||
void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height);
|
||||
void gfx_clear_color(u32 color);
|
||||
void gfx_con_init();
|
||||
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol);
|
||||
void gfx_con_getpos(u32 *x, u32 *y);
|
||||
void gfx_con_setpos(u32 x, u32 y);
|
||||
void gfx_putc(char c);
|
||||
void gfx_puts(const char *s);
|
||||
void gfx_puts(char *s);
|
||||
void gfx_printf(const char *fmt, ...);
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len);
|
||||
|
||||
void gfx_set_pixel(u32 x, u32 y, u32 color);
|
||||
void gfx_line(int x0, int y0, int x1, int y1, u32 color);
|
||||
void gfx_put_small_sep();
|
||||
void gfx_put_big_sep();
|
||||
void gfx_set_rect_grey(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
void gfx_set_rect_rgb(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
|
||||
void gfx_set_rect_argb_land(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
void gfx_fill_rect_argb(const u32 color, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
|
||||
|
||||
void gfx_set_rect_land_pitch(u32 *fb, const u32 *buf, u32 pos_x, u32 pos_y, u32 pos_x2, u32 pos_y2);
|
||||
void gfx_set_rect_land_block(const u32 *buf, u32 pos_x, u32 pos_y, u32 pos_x2, u32 pos_y2);
|
||||
void gfx_set_rect_land_pitch(u32 *fb, const u32 *buf, u32 stride, u32 pos_x, u32 pos_y, u32 pos_x2, u32 pos_y2);
|
||||
void gfx_set_rect_land_block(u32 *fb, const u32 *buf, u32 pos_x, u32 pos_y, u32 pos_x2, u32 pos_y2);
|
||||
|
||||
// Global gfx console and context.
|
||||
gfx_ctxt_t gfx_ctxt;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user