Page 2 sur 3

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 29 Mar 2022, 17:43
de parisse
Khi+KhiCAS n'essaie pas de prendre le controle de la flash interne. Si le bootloader de Phi est installe, c'est la version de Khi compatible qui est installee, sinon on propose l'installation du bootloader de Phi en plus (l'utilisateur peut refuser, dans ce cas c'est l'ancienne methode qui est utilisee).
Numworks va par contre tenter de prendre le controle de la flash interne pour installer son propre bootloader et prendre le controle de la calculatrice. La protection du bootloader de Phi empeche Numworks d'ecrire sur la flash interne par la liaison USB (la flash interne n'est meme pas lisible en fait).
Mais attention le bootloader de Phi n'est pas une protection contre l'ecriture en flash interne par un firmware hostile. On peut craindre qu'une prochaine version d'Epsilon verrouille la flash interne et la rende incompatible avec KhiCAS. Donc je ne le redirai jamais assez: si vous voulez continuer a garder le controle de votre calculatrice, ne faites plus de mise a jour chez Numworks et echangez vos scripts sans passer par le workshop (passez par mon kit de connexion https://www-fourier.univ-grenoble-alpes.fr/~parisse/nws.html ou un site non controle par Numworks).

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 30 Mar 2022, 00:02
de critor
M4x1m3 est tout fier de vous présenter ce soir screenhax, le bug qui a permis la naissance de Phi :
http://blog.mfriess.xyz/screenhax/

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 30 Mar 2022, 08:11
de Obilolo
parisse a écrit:Khi+KhiCAS n'essaie pas de prendre le controle de la flash interne. Si le bootloader de Phi est installe, c'est la version de Khi compatible qui est installee, sinon on propose l'installation du bootloader de Phi en plus (l'utilisateur peut refuser, dans ce cas c'est l'ancienne methode qui est utilisee).
Numworks va par contre tenter de prendre le controle de la flash interne pour installer son propre bootloader et prendre le controle de la calculatrice. La protection du bootloader de Phi empeche Numworks d'ecrire sur la flash interne par la liaison USB (la flash interne n'est meme pas lisible en fait).
Mais attention le bootloader de Phi n'est pas une protection contre l'ecriture en flash interne par un firmware hostile. On peut craindre qu'une prochaine version d'Epsilon verrouille la flash interne et la rende incompatible avec KhiCAS. Donc je ne le redirai jamais assez: si vous voulez continuer a garder le controle de votre calculatrice, ne faites plus de mise a jour chez Numworks et echangez vos scripts sans passer par le workshop (passez par mon kit de connexion https://www-fourier.univ-grenoble-alpes.fr/~parisse/nws.html ou un site non controle par Numworks).


Merci c'est plus clair. Mais donc ce n'est pas normal que l'installation khi slot A n'aie pas un KhiCAS fonctionnel. Je vais essayer de retenter l'installation en partant d'un epsilon sur les 2 slots.

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 30 Mar 2022, 08:43
de parisse
Obilolo a écrit:Merci c'est plus clair. Mais donc ce n'est pas normal que l'installation khi slot A n'aie pas un KhiCAS fonctionnel. Je vais essayer de retenter l'installation en partant d'un epsilon sur les 2 slots.

Ca ne servira a rien de reinstaller epsilon sur les 2 slots. Pour le moment, si on veut utiliser KhiCAS avec le bootloader de protection USB, la seule config qui marche est Khi (version bootloader) en slot A (fichier khi.A.bin en 0x90000000 taille environ 1.3M) et KhiCAS (fichier apps.tar en 0x92000000, taille un peu plus de 5M).

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 30 Mar 2022, 09:11
de parisse
J'avance dans le multiboot. Ma page kit de connexion devrait maintenant etre compatible avec un kernel qui tourne en 0x90400000.
Pour rendre le multi-boot compatible avec le mode examen (i.e. compatible avec reset-1 et reset-2), je pense que lors de l'activation/desactivation du mode examen, il suffirait de scanner toute la flash externe (8M) par secteurs de 4K (on peut aussi ne tester que tous les 64K), si on detecte un kernel header (au plus 4000 tests sur l'entier 32 bits a l'offset 0x8 si il vaut f0 0d c0 de), on regarde si le secteur suivant est compose d'une suite de bits entierement a 0 suivie par une suite de bits entierement a 1 (environ 1000 tests sur des entiers 32 bits), et si oui, on ecrit quelques 0 en fonction du nouveau mode examen.

Il y a un truc bizarre dans la zone de memoire flash du firmware dediee au mode examen. Pas grave, mais qui m'intrigue. Le fichier loader d'Omega est le suivant (bootloader_common.ld):
Code: Tout sélectionner
  .exam_mode_buffer ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.kernel_header) + SIZEOF(.isr_vector_table) : {
    . = ALIGN(4K);
    _exam_mode_buffer_start = .;
    KEEP(*(.exam_mode_buffer))
    /* Note: We don't increment "." here, we set it. */
    . = . + FIRST_FLASH_SECTOR_SIZE;
    _exam_mode_buffer_end = .;
  } >FLASH

FIRST_FLASH_SECTOR_SIZE est defini dans bootloader.A.ld (ou B) comme FIRST_FLASH_SECTOR_SIZE = 4K;
Or le dump de firmware me donne
Code: Tout sélectionner
901701e4 l    d  .exam_mode_buffer   00000000 .exam_mode_buffer
90171000 g       .exam_mode_buffer   00000000 _exam_mode_buffer_start
90171000 g     O .exam_mode_buffer   00001000 Ion::ExamMode::ones
90173000 g       .exam_mode_buffer   00000000 _exam_mode_buffer_end
90173000 l    d  .userland_header   00000000 .userland_header

Autrement dit on a une taille de 0x2000=8192 octets pour le buffer au lieu de 4096, et seulement 4096 octets sont remplis de 1 au demarrage. Dans exam_mode.cpp, on lit:
Code: Tout sélectionner
...
namespace Ion {
namespace ExamMode {

char ones[Config::ExamModeBufferSize]
  __attribute__((section(".exam_mode_buffer")))
  __attribute__((used))
= {EXAM_BUFFER_CONTENT};
...

donc la taille du tableau (qui devrait etre remplie par des 1) a une taille de Config::ExamModeBufferSize, dont la valeur est definie dans un autre fichier qui pour les N0110 est constexpr static int ExamModeBufferSize = 4*1024;

Donc on devrait pouvoir reduire d'un facteur 2 le buffer mode examen dans le fichier loader? A cet endroit, je pense que la taille des secteurs flash est de 4K, c'est necessaire pour que le buffer du mode examen puisse commencer en 0x90001000 apres le kernel header.

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 31 Mar 2022, 10:30
de parisse
Voila le code que je vais tester pour ajout dans apps/global_preferences.cpp pour la gestion du mode examen multi-boot:
Code: Tout sélectionner
/* begin section (c) B. Parisse, write exam mode in *all* firmwares */
// write exam mode mode to flash at offset pos/8
void write_exammode(unsigned char * ptr,int pos,int mode,int modulo){
  int curmode=pos%modulo;
  if (curmode == mode)
    return;
  int delta=(mode+modulo-curmode)%modulo; // 0<delta<modulo, number of bits that we will set to 0
  unsigned char * target = ptr + pos/8;
  int pos8=pos % 8; // number of bits already set to 0 at target
  pos8 += delta; // 0<pos8<modulo+7
  unsigned char postab[]={0b11111111,0b1111111,0b111111,0b11111,0b1111,0b111,0b11,0b1,0}; // postab[i] is a byte with i bits set to 0
  unsigned char tab[2];
  bool writenext=pos8>8;
  tab[0]=postab[writenext?8:pos8];
  tab[1]=postab[writenext?pos8-8:0];
#ifdef KHICAS
  Ion::Device::Flash::WriteMemory(target, tab, writenext?2:1);
#else
  target[0]=tab[0];
  if (writenext) target[1]=tab[1];
#endif
}

// check that region is split in two parts: bits set to 0 followed by bits set to 1, returns position of the first 1 bit or -1
int pos_01(unsigned * start,int l){
  unsigned *ptr=start,* end=start+l/sizeof(unsigned);
  for (;ptr<end;++ptr){
    if (*ptr)
      break;
  }
  if (ptr==end)
    return -1;
  int pos=(ptr-start)*32;
  unsigned char * ptr8=(unsigned char *) ptr;
  if (*ptr8==0){
    pos+=8; ++ptr8;
  }
  if (*ptr8==0){
    pos+=8; ++ptr8;
  }
  if (*ptr8==0){
    pos+=8; ++ptr8;
  }
  switch (*ptr8){
  case 0b1: pos+=7; break; // 7 bits are already set to 0
  case 0b11: pos+=6; break;
  case 0b111: pos+=5; break;
  case 0b1111: pos+=4; break;
  case 0b11111: pos+=3; break;
  case 0b111111: pos+=2; break;
  case 0b1111111: pos+=1; break;
  case 0b11111111: break;
  default: return -1;
  }
  ++ptr;
  for (;ptr<end;++ptr){
    if (*ptr!=0xffffffff)
      return -1;
  }
  return pos;
}

char print_hex(int val){
  val &= 0xf;
  if (val>=0 && val<=9)
    return '0'+val;
  return 'A'+(val-10);
}

void print_hex(unsigned val,char * ptr){
  for (int i=0;i<8;++i){
    ptr[i]=print_hex(val>>(28-4*i));
  }
}

void set_exammode(int mode,int modulo){
  if (mode<0 || mode>=modulo)
    return;
  // scan external flash every dflash bytes
  unsigned * flashptr=(unsigned *) 0x90000000;
  unsigned dflash=0x10000,ntests=8*1024*1024/dflash/sizeof(unsigned);
  for (unsigned i=0;i<ntests;++i){
    unsigned * ptr=flashptr+i*dflash;
    if (0){
      extapp_pushRectUniform(0,100,320,100,0);
      char tab[9]={0};
      print_hex((unsigned)ptr,tab);
      extapp_drawTextSmall(tab,0,100,65535,0,false);
      print_hex(*(ptr),tab);
      extapp_drawTextSmall(tab,0,120,65535,0,false);
      print_hex(*(ptr+1),tab);
      extapp_drawTextSmall(tab,0,140,65535,0,false);
      print_hex(*(ptr+2),tab);
      extapp_drawTextSmall(tab,0,160,65535,0,false);
      extapp_getKey(false,0);
    }
    // kernel header?
    if (*ptr!=0xffffffff || *(ptr+1)!=0xffffffff || *(ptr+2)!= 0xdec00df0 /* f0 0d c0 de*/)
      continue;
    ptr += 0x1000/sizeof(unsigned); // exam mode buffer?
    int pos=pos_01(ptr,0x1000);
    if (pos==-1)
      continue;
    if (pos>=0x1000-8){
      Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress((uint32_t)ptr));
      pos=0;
    }
    if (0){
      extapp_pushRectUniform(0,100,320,100,0);
      char tab[9]={0};
      print_hex((unsigned) ptr,tab);
      extapp_drawTextSmall(tab,0,100,65535,0,false);
      print_hex(pos,tab);
      extapp_drawTextSmall(tab,0,130,65535,0,false);
      extapp_getKey(false,0);
    }
    write_exammode((unsigned char *)ptr,pos,mode,modulo);
  }
}
/* end section (c) B. Parisse, */

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 31 Mar 2022, 15:55
de parisse
Mise a jour du code ci-desus apres correction.

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 31 Mar 2022, 20:04
de parisse
Mise a jour de https://www-fourier.univ-grenoble-alpes.fr/~parisse/nws.html. Les nouveautes: possibilite d'installer un multi-boot adapte a KhiCAS avec Khi "normal" ou un autre firmware en slot A et un Khi minimal dans un slot B deplace en 0x90180000. Ce Khi minimal permet uniquement de lancer les apps externes (qui sont en 0x90200000) mais avec un avantage: il y a plus de memoire disponible pour les applications. Attention, vous ne pouvez pas booter Khi slot B adapte KhiCAS depuis le bootloader d'Omega (le slot B n'est pas a la meme adresse).
Si vous installez les deux versions de Khi, votre calculatrice beneficie d'une protection contre des mises a jour potentiellement hostiles (pouvant par exemple verrouiller la calculatrice).
Les deux firmwares gerent le mode examen en conformite avec la reglementation francaise, vous pouvez changez de slot avec reset+1 ou reset+2, le mode examen est reporte sur l'autre firmware en cas de changement.

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 31 Mar 2022, 20:26
de critor
Autre actualité à ce sujet - c'est toujours bon de voir ce que ça donne d'un autre point de vue :
https://www.planet-casio.com/Fr/forums/ ... tml#187243

Re: Khi pour N0110, nouveau firmware compatible multiboot Ph

Message non luPosté: 31 Mar 2022, 20:33
de parisse
P.S.: la protection du multiboot+Khi A+Khi B est partielle. Il vaut toujours mieux eviter d'aller sur des sites potentiellement hostiles!