
J'ai donc eu une idée d'un nouveau programme Ndless qui :
- marque le mode examen comme étant à activer au prochain démarrage - juste à reflasher la zone NAND Boot Data, voir la doc Hackspire -> https://hackspire.org/index.php/NAND_Memory_Layout
- effectue un redémarrage à chaud de l'OS, comme l'installateur Ndless 3.6 -> https://github.com/ndless-nspire/Ndless ... stage2.cpp
Je ne partagerai pas le code permettant d'éditer la zone BootData dans l'immédiat, car il n'est pas user-friendly et permet de faire des bêtises, dont des blocages définitifs de la machine si on n'a pas d'outil de secours comme nBoot+ControlX.
Par contre, niveau redémarrage à chaud :
- Code: Select all
#include "os.h"
typedef unsigned long int uint32_t;
typedef unsigned short int uint16_t;
typedef unsigned char uint8_t;
void clear_cache()
{
unsigned dummy;
__asm volatile(
"0: mrc p15, 0, r15, c7, c10, 3 @ test and clean DCache \n"
" bne 0b \n"
" mov %0, #0 \n"
" mcr p15, 0, %0, c7, c7, 0 @ invalidate ICache and DCache \n" : "=r" (dummy));
}
void memset32(uint32_t* a, uint32_t b, uint32_t c) {
c/=4;
while(c--)
*(a++)=b;
}
// As expected by the patch headers generated by MakeHotRebootPtch
#define PATCH_SETW(A,B) *(uint32_t *)(A) = (B)
#define PATCH_SETZ(A,B,C) memset32((uint32_t *)(A), (C), (B)-(A))
static void write_i2c(uint8_t client, uint8_t addr, uint8_t value) {
PATCH_SETW(0x9005006c, 0); //Disable I2C
PATCH_SETW(0x90050004, client); //Set target address
PATCH_SETW(0x9005006c, 1); //Enable I2C
volatile uint32_t *status = (uint32_t*) 0x90050070;
PATCH_SETW(0x90050010, addr);
while(*status & 1); //Wait until transmitted
PATCH_SETW(0x90050010, value);
while(*status & 1); //Wait until transmitted
}
static void write_touchpad(uint16_t port, uint8_t value) {
write_i2c(0x20, 0xFF, port >> 8);
write_i2c(0x20, port & 0xFF, value);
}
void main() {
uint8_t i;
// Disable all interrupts
if (!has_colors) {
PATCH_SETW(0xDC00000C, 0xFFFFFFFF);
} else {
PATCH_SETW(0xDC000014, 0xFFFFFFFF);
}
if (!has_colors) {
uint32_t RX;
__asm volatile (
"mrs %0, cpsr \n"
"bic %0, %0, #0x80 \n"
"msr cpsr_c, %0 \n"
: "=r" (RX));
}
if (!has_colors) {
uint32_t dummyint = *((volatile uint32_t *)(0xDC000028));
(void)dummyint; // unused warning
}
// Reset IRQ flags
if (has_colors) {
PATCH_SETW(0x90010008, 0);
PATCH_SETW(0x90010008, 0);
PATCH_SETW(0x9001000C, 1);
PATCH_SETW(0x90010028, 0);
PATCH_SETW(0x9001002C, 1);
PATCH_SETW(0x900C0008, 0);
PATCH_SETW(0x900C000C, 1);
PATCH_SETW(0x900C0028, 0);
PATCH_SETW(0x900C002C, 1);
PATCH_SETW(0x900D0008, 0);
PATCH_SETW(0x900D000C, 1);
PATCH_SETW(0x900D0028, 0);
PATCH_SETW(0x900D002c, 1);
}
//Reset USB
volatile int z;
PATCH_SETW(0x900B0018, *(volatile uint32_t*)0x900B0018 & 0b11111111111111111111111110011111);
for (z = 0; z <= 0x10000; z++)
;
uint32_t usb_cmd = *((volatile uint32_t *)(0xB0000140));
usb_cmd &= ~1;
PATCH_SETW(0xB0000140, usb_cmd);
PATCH_SETW(0xB4000140, usb_cmd);
for (z = 0; z <= 0x10000; z++)
;
usb_cmd = *((volatile uint32_t *)(0xB0000140));
usb_cmd |= 0x2;
PATCH_SETW(0xB0000140, usb_cmd);
while ( ((*((volatile uint32_t *)(0xB0000140)))&0x2) != 0x0 )
;
PATCH_SETW(0xB00001A4, 0x003C1120);
if (has_colors) {
// Reset touchpad
write_touchpad(0x0004, 0x01);
// Disable I2C IRQ
PATCH_SETW(0x90050030, 0);
// Disable I2C
PATCH_SETW(0x9005006C, 0);
}
// Disable RTC IRQ
PATCH_SETW(0x9009000C, 1);
// Disable keypad and touchpad IRQs
PATCH_SETW(0x900E000C, 0);
PATCH_SETW(0x900E0040, 0);
// Reset OS global variables to their initial values
// Reset internal RAM state, else unstable without USB plugged-in
switch (4) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
#include "hrpatches-os-cascx-3.6.0.h"
case 4:
#include "hrpatches-os-cascx-4.4.0.h"
break;
}
clear_cache();
((void(*)(void))0x10000000)(); // Hot-reboot the OS
__builtin_unreachable();
}
Le projet est énorme/complexe, vu que l'OS une fois lancé n'est plus redémarrable, car auto-modifiant son propre code.
Il faut donc avoir une série de patchs pour chaque version d'OS permettant d'annuler ces modifications avant de redémarrer.
Voici celles de l'OS 4.4 CX CAS obtenues en suivant les instructions sur https://github.com/ndless-nspire/Ndless ... ootPatches :
- Code: Select all
/* This file was initially generated with MakeHotRebootPtch */
PATCH_SETW(0x10000028, 0x103AA65C);
PATCH_SETW(0x1000ACD8, 0xE1A03000);
PATCH_SETW(0x1000ACDC, 0xEAFFFFE0);
PATCH_SETW(0x10031034, 0xE2504000);
PATCH_SETW(0x10031038, 0xE24DD010);
PATCH_SETW(0x10082B18, 0xE92D45F8);
PATCH_SETW(0x10082B1C, 0xE59D7020);
PATCH_SETW(0x10123B14, 0x0A000004);
PATCH_SETW(0x1013FC70, 0xE1A00006);
PATCH_SETW(0x1013FC74, 0xE59F1050);
PATCH_SETW(0x1086666C, 0xE5901010);
PATCH_SETW(0x10866670, 0xE5914070);
PATCH_SETW(0x10BC5150, 0x00000000);
PATCH_SETW(0x10BC5188, 0x00000000);
PATCH_SETW(0x10BC51D4, 0x00000000);
PATCH_SETW(0x10BC5268, 0xFFFFFFFF);
PATCH_SETW(0x10BC5274, 0x11FDA800);
PATCH_SETW(0x10BC9C04, 0xFFFFFFFF);
PATCH_SETW(0x10CA1940, 0x00000000);
PATCH_SETW(0x10CA3668, 0x00000000);
PATCH_SETZ(0x10CA3680, 0x10CA44DC, 0x00000000);
PATCH_SETW(0x10D9651C, 0x00000000);
PATCH_SETW(0x10D98244, 0x00000000);
PATCH_SETZ(0x10D9825C, 0x10D988C4, 0x00000000);
PATCH_SETW(0x10E8CF80, 0x00000000);
PATCH_SETW(0x10E8EE70, 0x00000000);
PATCH_SETZ(0x10E8EE88, 0x10E8F0A4, 0x00000000);
PATCH_SETW(0x10E94070, 0x00000000);
PATCH_SETW(0x10E95D98, 0x00000000);
PATCH_SETZ(0x10E95DB0, 0x10E96268, 0x00000000);
PATCH_SETW(0x10E9D490, 0x00000000);
PATCH_SETW(0x10E9F1B8, 0x00000000);
PATCH_SETZ(0x10E9F1D0, 0x10E9FEB0, 0x00000000);
PATCH_SETW(0x10EA812C, 0x00000000);
PATCH_SETW(0x10EA9E54, 0x00000000);
PATCH_SETZ(0x10EA9E6C, 0x10EAA420, 0x00000000);
PATCH_SETW(0x10F1D598, 0x00000000);
PATCH_SETW(0x10F1F2C0, 0x00000000);
PATCH_SETZ(0x10F1F2D8, 0x10F1F81C, 0x00000000);
PATCH_SETW(0x10F289A8, 0x00000000);
PATCH_SETW(0x10F2A6D0, 0x00000000);
PATCH_SETZ(0x10F2A6E8, 0x10F2ACE0, 0x00000000);
PATCH_SETW(0x10F45820, 0x00000000);
PATCH_SETW(0x10F47548, 0x00000000);
PATCH_SETZ(0x10F47560, 0x10F47DA0, 0x00000000);
PATCH_SETZ(0x112DDA7C, 0x112DDABC, 0x00000000);
PATCH_SETZ(0x112DECE0, 0x112DED20, 0x00000000);
PATCH_SETZ(0x112DED3C, 0x112DED80, 0x00000000);
PATCH_SETW(0x112DED84, 0x00000004);
PATCH_SETW(0x112DED88, 0x00000009);
PATCH_SETW(0x112DED8C, 0x00000010);
PATCH_SETW(0x112DED90, 0x00000020);
PATCH_SETW(0x112DED94, 0x00000800);
PATCH_SETW(0x112DED98, 0x000007D8);
PATCH_SETW(0x112DED9C, 0x10AA1AF4);
PATCH_SETW(0x112DEE24, 0x1008F900);
PATCH_SETW(0x112DEE3C, 0x100924C8);
PATCH_SETW(0x112DEE44, 0x100924C8);
PATCH_SETW(0x112DEE4C, 0x100924C8);
PATCH_SETW(0x112DEE54, 0x100924C8);
PATCH_SETW(0x112DEE5C, 0x100924C8);
PATCH_SETW(0x112DEE64, 0x100924C8);
PATCH_SETZ(0x112DEE84, 0x112DEE8C, 0x00000001);
PATCH_SETW(0x112DEE8C, 0x10B306F4);
PATCH_SETW(0x112DEEB0, 0x00000000);
PATCH_SETW(0x112DEEC4, 0x00000000);
PATCH_SETW(0x112DEED8, 0x00000000);
PATCH_SETW(0x112DEEEC, 0x00000000);
PATCH_SETW(0x112DEF00, 0x00000000);
PATCH_SETW(0x112DEF14, 0x00000000);
PATCH_SETW(0x112DEF28, 0x00000000);
PATCH_SETW(0x112DEF3C, 0x00000000);
PATCH_SETW(0x112DEF50, 0x00000000);
PATCH_SETW(0x112DEF58, 0x00000001);
PATCH_SETZ(0x112DEF74, 0x112DEFB4, 0x00000000);
PATCH_SETW(0x112DEFB4, 0x00FF00FF);
PATCH_SETW(0x112DEFC0, 0x00000065);
PATCH_SETW(0x112DEFC4, 0x00000000);
PATCH_SETW(0x112DF038, 0x636E742E);
PATCH_SETW(0x112DF03C, 0x6E742E3B);
PATCH_SETW(0x112DF040, 0x0000006F);
PATCH_SETZ(0x112DF078, 0x112DF0B8, 0x00000000);
PATCH_SETZ(0x112DF0D0, 0x112DF100, 0x00000000);
PATCH_SETZ(0x112DF20C, 0x112DF23C, 0x00000000);
PATCH_SETW(0x112DF394, 0x0FC00000);
PATCH_SETW(0x112DF39C, 0x0000001E);
PATCH_SETW(0x112DF3A0, 0x00000059);
PATCH_SETW(0x112DF3A4, 0x00000064);
PATCH_SETW(0x112DF3A8, 0x000007D0);
PATCH_SETZ(0x112DF3D0, 0x112DF410, 0x00000000);
PATCH_SETZ(0x112DF428, 0x112DF468, 0x00000000);
PATCH_SETZ(0x112DF488, 0x112DF4B4, 0x00000000);
PATCH_SETW(0x112DF594, 0x00000001);
PATCH_SETW(0x112DF598, 0x00000000);
PATCH_SETZ(0x112DF5D8, 0x112DF644, 0x00000000);
PATCH_SETW(0x112DFA28, 0x80000000);
PATCH_SETW(0x112DFA2C, 0x00002000);
PATCH_SETW(0x112DFB04, 0x00000007);
PATCH_SETW(0x112DFB08, 0x00000096);
PATCH_SETW(0x112E1AE0, 0x00000000);
PATCH_SETZ(0x112E1B08, 0x112E1B48, 0x00000000);
PATCH_SETZ(0x112E1B60, 0x112E1BA0, 0x00000000);
PATCH_SETZ(0x112E1BB0, 0x112E1BEC, 0x00000000);
PATCH_SETW(0x112E4D70, 0x10AE0258);
PATCH_SETZ(0x112E4E00, 0x112E4E40, 0x00000000);
PATCH_SETZ(0x112E4E4C, 0x112E4E88, 0x00000000);
PATCH_SETZ(0x112E4EC8, 0x112E4F00, 0x00000000);
PATCH_SETZ(0x112E4F30, 0x112E4F6C, 0x00000000);
PATCH_SETZ(0x112E4F78, 0x112E4F80, 0x00000000);
PATCH_SETZ(0x112E4F88, 0x112E4FC4, 0x00000000);
PATCH_SETZ(0x112E4FD0, 0x112E4FD8, 0x00000000);
PATCH_SETZ(0x112E4FE0, 0x112E501C, 0x00000000);
PATCH_SETZ(0x112E5028, 0x112E5030, 0x00000000);
PATCH_SETZ(0x112E5038, 0x112E5074, 0x00000000);
PATCH_SETZ(0x112E5080, 0x112E5088, 0x00000000);
PATCH_SETZ(0x112E5090, 0x112E50CC, 0x00000000);
PATCH_SETZ(0x112E50D8, 0x112E50E0, 0x00000000);
PATCH_SETZ(0x112E50E8, 0x112E50FC, 0x1142AD0C);
PATCH_SETW(0x112E9B20, 0x00000001);
PATCH_SETW(0x112F1BF0, 0xFFFFFFFF);
PATCH_SETZ(0x112F33B4, 0x112F33BC, 0xFFFFFFFF);
PATCH_SETW(0x112F3CF0, 0x00000001);
PATCH_SETW(0x112F3D30, 0x000000FF);
PATCH_SETW(0x112F3D3C, 0x00000000);
PATCH_SETZ(0x112F3D7C, 0x112F3DE8, 0x00000000);
PATCH_SETW(0x112F3F28, 0x00000000);
PATCH_SETZ(0x112F3F68, 0x112F3FD4, 0x00000000);
PATCH_SETW(0x112F8300, 0x00000001);
PATCH_SETW(0x112F83D4, 0xFFFFFFFF);
PATCH_SETW(0x112F83D8, 0x00000001);
PATCH_SETZ(0x112F985C, 0x112F987C, 0x00000000);
PATCH_SETW(0x112F98E8, 0x00000000);
PATCH_SETW(0x112FA368, 0x00003200);
PATCH_SETW(0x112FA398, 0x04510007);
PATCH_SETW(0x112FA468, 0x00000000);
PATCH_SETW(0x112FA688, 0x00000002);
PATCH_SETZ(0x112FA69C, 0x112FA6AC, 0x00000000);
PATCH_SETW(0x112FA6B0, 0x08000000);
PATCH_SETZ(0x112FA6B4, 0x112FA6C0, 0x00000000);
PATCH_SETW(0x112FA6C0, 0x00000209);
PATCH_SETW(0x112FA6C4, 0x80000000);
PATCH_SETW(0x112FA6C8, 0x00000032);
PATCH_SETW(0x112FA6CC, 0x00000903);
PATCH_SETW(0x112FA6D4, 0x00000000);
PATCH_SETW(0x112FA6DC, 0x00000507);
PATCH_SETZ(0x112FA6E0, 0x112FA6E8, 0x00000000);
PATCH_SETW(0x112FA6E8, 0x112FA6E4);
PATCH_SETW(0x112FA6EC, 0x10B306F4);
PATCH_SETZ(0x112FA720, 0x112FA728, 0x00000001);
PATCH_SETW(0x112FA730, 0x00000000);
PATCH_SETW(0x112FA7C4, 0x00000000);
PATCH_SETW(0x112FA800, 0x00000000);
PATCH_SETW(0x112FA850, 0x00000000);
PATCH_SETW(0x112FA854, 0x112FA850);
PATCH_SETW(0x112FA864, 0x00000000);
PATCH_SETW(0x112FA868, 0x112FA864);
PATCH_SETZ(0x112FA890, 0x112FA8B0, 0x00000000);
PATCH_SETZ(0x112FA8B0, 0x112FA8BC, 0xFFFFFFFF);
PATCH_SETW(0x112FADA4, 0x1142AD0C);
PATCH_SETW(0x112FADAC, 0x00000001);
PATCH_SETW(0x112FB1EC, 0x1142AD0C);
PATCH_SETW(0x112FB6E4, 0x00000001);
PATCH_SETW(0x112FE648, 0x00000000);
PATCH_SETZ(0x112FE660, 0x112FE7F0, 0x00000000);
PATCH_SETW(0x11303054, 0x00000000);
PATCH_SETW(0x1130436C, 0x00000001);
PATCH_SETW(0x1134ADA0, 0x00000002);
PATCH_SETW(0x11389DA8, 0x10B47A30);
PATCH_SETW(0x11389EC0, 0x00000000);
PATCH_SETZ(0x11389EE4, 0x1138B0B4, 0x00000000);
PATCH_SETZ(0x1138B0F0, 0x1138B15C, 0x00000000);
PATCH_SETZ(0x1138BB2C, 0x1138BB50, 0x00230023);
PATCH_SETZ(0x1138BD2C, 0x1138BD50, 0x002A002A);
PATCH_SETZ(0x1138BF2C, 0x1138BF50, 0x00230023);
PATCH_SETW(0x1138BF50, 0x00000023);
PATCH_SETZ(0x1138C12C, 0x1138C150, 0x002A002A);
PATCH_SETW(0x1138C150, 0x0000002A);
PATCH_SETZ(0x1138C32C, 0x1138C350, 0x00230023);
PATCH_SETZ(0x1138C52C, 0x1138C550, 0x002A002A);
PATCH_SETZ(0x1138C7CC, 0x1138C80C, 0x00000000);
PATCH_SETW(0x1138C810, 0x00000503);
PATCH_SETW(0x113929BC, 0x00000000);
PATCH_SETW(0x113929C8, 0x00000000);
En pratique ?
- On enregistre pour le prochain démarrage de l'OS le mode examen que l'on veut :
- On lance l'outil de redémarrage à chaud.
- Le redémarrage à chaud de l'OS CX CAS 4.4 marche, on est de retour à l'écran d'accueil en seulement quelques secondes.
Toutefois l'état final n'est pas parfaitement stable - sans doute manque-t-il encore un peu de travail sur les patchs. - L'OS une fois redémarré dit bien qu'il est en mode examen.
- Mais hélas, la diode ne clignote pas, du moins pas avant un reset complet de la machine.
En conséquence, je me vois contraint d'abandonner ce projet - faites ce que vous voulez du code et des infos.