Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » Idée de projet - add-in pour debug
Yatis Hors ligne Membre Points: 581 Défis: 0 Message

Idée de projet - add-in pour debug

Posté le 28/05/2018 20:01

salut;
Je sais pas si vous programmez sur Casio mais si c’est le cas vous devez savoir à quel point programmer dessus c’est pratique: on programme un jeu, on le compile, on vérifie sur l’Émulateur si tout fonctionne, si tout fonctionne on le transfère sur la calto puis on peut transporter son jeu de partout.



Problématique
Si vous programmez un gros jeu il est possible que des petits bugs apparaissent APRÈS avoir compilé qui font planter la Casio.
Et pourtant le jeu fonctionnait sur l’Émulateur sauf que l’Émulateur ne sera jamais comme la console.
Et c’est là que ça devient méga chiant parce que, modifier un octet, compiler, connecter la calto et voir que ça ne fonctionne pas...on vient de perdre 5 minutes de notre vie à brasser de l’aire.
De plus si vos faites des jeux en multijoueur on ne peut pas vérifier via l’Émulateur, il faut donc tout se taper et c’est...long, trop long.



Idée
C’est pourquoi une idée m’est venue alors que j’écrivais la librairie “mySerail.h”.
Pourquoi ne pas créer un add-in qui récupère les données via le port USB puis exécute le jeu à la fin du transfère ?
Pour résumer éviter d’aller dans “LINK”, et attendre que la calto se connecte à l’ordi, attendre que l’add-in soit transféré.
En gros avoir un add-in de debug qui nous permet de ne pas avoir à toucher à la console pour tester ses programmes.



Théorie
Pour ça il nous faut une connexion directe entre la Casio et le PC...bon ya un port USB donc c’est rapide.
L’add-in se met directement en ‘Receive’ (elle attend un fichier).
Ensuite on vérifie s'il y a assez de place dans la RAM.
Si ya assez de place, on met tout le programme dans la RAM, puis on l’exécute. (c’est tellement simple à dire^^)
Pourquoi la RAM ?
C’est un add-in de debug je vous rappelle donc on s’en fout que le programme soit stocké dans la ROM.
De plus la RAM est rapide à écrire, bien plus rapide que le ROM.



Possible ?
Oui MAIS seulement des petits programmes car la ‘vrai’ RAM disponible sur SH4 est de 12 ko (d’après la doc de Lephenixoir) OU 64 ko (d’après le wiki).
Donc bon...
Oublions 2 secondes la taille de la RAM et le fait qu’il y en est pas autant sur les SH3 que sur le SH4.
1.On sait communiquer via le port USB (exemple : P7 de Cakeisalie5), du moins on sait communiquer PC->Casio par contre il me semble pas avoir entendu parler de syscall permettant de jouer avec le port USB (j’ai chercher mais je n'ai rien comprit ).

2.On sait exécuter du code Assembleur depuis la RAM (#sysCall) (gint fait ça merveilleusement bien aussi <3).

3.On sait faire des interfaces par dégueux.
Donc oui c’est possible !



Es-ce que j’ai commencer a faire un truc ?
Non, déjà parce que j'ai pas beaucoup de temps en ce moment et j’ai déjà plusieurs projets à finir.
C’est juste pour signaler que c’est théoriquement possible donc s'il y a des personnes intéressées par ce projet...bah allez-y ça pourrait être sympa et il y a sûrement beaucoup de choses à apprendre .


Précédente 1, 2, 3, 4, 5, 6
Lephenixnoir Hors ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 19/03/2019 17:19 | #


Cette mémoire est "découpée" permettant de communiquer avec des modules autour du MPU (RTC, TMU, écran, KEYSC, etc...).

La mémoire virtuelle est une interface avec tout un paquet de hardware, notamment la RAM physique, la ROM, et les modules périphériques. Il y a des adresses virtuelles qui pointent vers chacune de ces régions.

Cependant je ne comprends pas comment elle est organisée, en fait, pour être exact, je n'arrive pas à saisir ce que représentente les zones P0, P1, P2, P3 et P4

La séparation est arbitraire. Elle existe car selon les moments on veut utiliser des zones de mémoire avec des propriétés différentes.

* P0 est la seule zone accessible en mode utilisateur (le contraire du mode privilégié du processeur). Dans un vrai OS, les programmes tournent en mode utilisateur et ne peuvent donc utiliser que des adresses dans la première moitié de l'espace. Cette partie peut être gérée par le MMU, ce qui permet au kernel de charger les exécutables en mémoire et tout ça.

* P1 et P2 sont deux zones où le MMU n'est pas actif, ce qui en font des fenêtres directes sur la mémoire physique. Dans le MPU que l'on utilise, les adresses physiques font 29 bits donc l'adresse physique associée à une adresse virtuelle est obtenue en effaçant les 3 bits du haut. Tu remarques donc que P1 et P2 pointent vers la même mémoire (au début de l'espace il y a la ROM, plus loin il y a la RAM). Toutefois P1 et P2 n'ont pas les mêmes paramètres de cache, l'une des zones peut exploiter le cache tandis que l'autre non.

* P3 est quasiment inutilisé pour nous, de mémoire il n'y a que la RAM on-chip qui est mappée ici (en dur, pas par le MMU).

* P4 est un espace un peu fourre-tout dont les adresses sont mappées individuellement vers les modules périphériques.

L'addresses des modules autour du MPU commence par 0xa donc ils se trouvent dans la zone P2 ?

Oui, mais pas tous les modules sont là, un certain nombre est dans P4.

Les zones cachable (a savoir P0, P1, P3) signifie qu'on peut lire et ecrire dedans ?

Non, ça signifie que le cache est actif (le cache étant cet intermédiaire entre le processeur et la mémoire, qui est plus petit et plus près du CPU que la RAM et donc plus rapide, et qui essaie de prévoir ce que le processeur va utiliser pour le charger en avance et limiter les interactions avec la RAM). Cela dit il n'y a pas de cache sur SH3 à ma connaissance (remplacé par la on-chip RAM) et sur SH4 je n'ai jamais trop su s'il y en avait un non plus.

La zone P0 commence a 0x00000000 mais pourtant la RAM démarre a 0x08100000, pourquoi ?

La zone P0 est une zone entièrement gérée par le MMU, on peut donc la remplir comme on veut. On peut met l'add-in à 0x00300200 mais n'importe quelle autre adresse marcherait aussi. Pour la RAM, c'est pareil.

En l'occurrence cette RAM est dans P0 parce que l'OS fait les choses à peu près correctement : en principe l'add-in devrait tourner sur le mode utilisateur du processeur, ce qui lui interdit d'accéder à la partie haute de la mémoire, il n'a accès qu'à P0. Et donc l'OS mappe la partie appropriée de la ROM et la RAM statique quelque part dans P0, pour que l'add-in puisse y accéder. (En réalité l'add-in tourne en mode privilégié, mais ça c'est parce qu'ils font n'importe quoi...)

Quand tu comprendras un peu mieux, interroge-toi sur la question suivante : puisque ton add-in est mappé par le système, peux-tu facilement mapper tes propres processus dans P0 sans risquer des interférences ?

La zone P4 contient...des registres ? (TEA, TRA, EXEVT, INTEVT, etc...) ?

La zone P4 est un petit bordel et il y a des fils dans le processeur qui interceptent les accès à l'adresse 0xff000020 pour les renvoyer vers le registre TRA. C'est des adresses affectées au cas-par-cas. Ce n'est pas de la "mémoire" au sens RAM, c'est juste une adresse virtuelle envoyée vers un registre.

La zone de 256ko dont tu me parlais est la zone P3 ? Pourtant elle fait ((0xe00000000 - 0xc0000000) / 1024) 524 288ko ... je ... je ... comprends pas...en fait je me rends compte que je ne sais absolument rien sur la mémoire Et j'ai un peut honte d'avoir dit que je faisais un kernel alors que je ne connais rien sur les points les plus importants d'un tel projet

Nope, c'est pas vraiment ça. La ROM et la RAM sont situées aux adresses physiques 0x00000000 et 0x08000000, respectivement. Ça veut dire que tu peux y accéder de plusieurs façons :

* En utilisant une adresse de P0 qui a été redirigée vers une de ces adresses physiques dans le MMU ;
* En utilisant les zones aux adresses 0x80000000 et 0x88000000 (rappelle-toi que le MMU est inactif dans P1, donc tu mets les 3 bits du haut à 0 et ça te donne l'adresse physique) ;
* En utilisant les zones équivamentes de P2 à 0xa0000000 et 0xa8000000.

En général, on passe dans P1, donc on considère que la RAM qui est à l'adresse physique 0x08000000 est exposée dans l'espace virtuel à l'adresse 0x88000000. Il y a bien longtemps, la RAM faisait 256k, ce qui signifie qu'accéder n'importe où entre 0x88000000 et 0x88040000 (exclue) envoyait dans la RAM. Aller plus loin envoyait dans le vide, sans doutes des zéros ou des erreurs...

Mais depuis que la RAM fait 512k (longtemps), on peut aller plus loin parce qu'on a remarqué que les adresses virtuelles 0x88040000 à 0x88080000 (exclue) pointent aussi vers de la mémoire (puisqu'on peut lire, écrire, et les changements persistent). Tu peux aussi y accéder via la zone 0xa8040000 à 0xa8080000 (exclue), qui pointe vers la même mémoire physique, mais on ne le fait jamais.

Tu n'aurais pas quelques bocquins à me recommander pour un néophyte comme moi ? (Tu m'as montré l'auteur Andrew S. Tanenbaum, mais je préfère reposer la question histoire de me souvenir des noms ).

Oui, le Modern Operating Systems de Tanenbaum est bien, la moitié sur les sytèmes centralisés (classiques) est très accessibles. De mémoire dès le troisième chapitre on est sur la gestion de la mémoire. Tout le reste est très intéressant également.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Yatis Hors ligne Membre Points: 581 Défis: 0 Message

Citer : Posté le 19/03/2019 19:44 | #


Quand tu comprendras un peu mieux, interroge-toi sur la question suivante : puisque ton add-in est mappé par le système, peux-tu facilement mapper tes propres processus dans P0 sans risquer des interférences ?

À part connaitre exactement ce qui se trouve dans cette zone, non ça me semble impossible.
Ou alors je peux les mapper directement dans P0 sans que ce sois un problème (?) Dans tous les cas il faut absolument que le kernel ne sois pas dans P0 (dans P1 je pense) et qu'il sache exactement où sont mappés les processus (qui eux seront dans P0) (?)

Ou alors: (mais ça me semble moins stable)
Tu a expliqué que la RAM vas (physiquement) de 0x08000000 jusqu'à 0x08080000, je pourrais la deviser en 2, loader le noyau dans la seconde partie puis charger les processus dans la première partie. Le problème c'est que je vais avoir besoin de les mapper moi-même donc le MMU ne doit pas s'en mêler...donc passer par P1 (je pense) ce qui va m'empêcher de passer le processeur en mode "user"...(?). Mais part contre je saurais exactement ou sont mappé les processus.
Je vais surement risquer d'écraser des données de l'OS de Casio si je fais ça, non ?
C'est bête comme idée ?

Merci beaucoup de m'avoir expliqué tout ça, j'y vois un peu plus claire maintenant <3
Lephenixnoir Hors ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 19/03/2019 22:18 | #


Ton intuition est bonne. En général, le kernel est mappé à une adresse fixe dans tous les espaces d'adressages des processus, par exemple dans P1 ou P2, peu importe. Ça te permet d'invoquer du code du kernel quand tu fais trapa sans avoir à recharger la configuration du MMU, ce qui serait coûteux (btw le patch contre Meltdown du doux nom de KPTI, correspond à mettre le kernel dans un autre espace d'adressage et ça a un gros coût sur les performances).

Oui, c'est possible de couper la RAM en deux comme tu dis. Après tu ne veux pas que les processus normaux, qui n'ont pas accès à P1, puissent lire le noyau, donc il faudra faire attention à ce que seule la première moitié soit mappée dans P0 !

Tout ce que tu dis dans ce paragraphe est juste : tu as ce problème que si le processus doit pouvoir accéder à P1 alors tu dois garder le mode privilégié du processeur, ce qui est une mauvaise idée (car je pourrai lancer gint caché dans ls et prendre contrôle de ton noyau).

En principe tu devrais le charger dans la RAM, mapper la zone appropriée dans P0, et le laisser en mode utilisateur. Mieux encore, tu peux mapper directement le programme de la ROM vers P0 (attention à la fragmentation dans le fs de la mémoire de stockage).

Tu ne peux définitivement pas modifier n'importe quelle partie de la RAM. Par contre la deuxième moitié, jusque-là c'est open bar. Donc tu peux toujours laisser la première moitié à sa place et couper la deuxième en deux...

Bon courage, tu progresses !
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Yatis Hors ligne Membre Points: 581 Défis: 0 Message

Citer : Posté le 23/03/2019 18:22 | #


Ton intuition est bonne. En général, le kernel est mappé à une adresse fixe dans tous les espaces d'adressages des processus, par exemple dans P1 ou P2, peu importe. Ça te permet d'invoquer du code du kernel quand tu fais trapa sans avoir à recharger la configuration du MMU, ce qui serait coûteux

J'ai commencé la re-structuration du projet. Et en ce moment je suis sur le bootstrap.
Ce sera un simple shell avec 2 / 3 commandes sans plus: ls (smem), load (ELF format), check(ELF header) et son objectif sera de loader le noyau (stoker dans un fichier ELF) dans P1.

En ce moment j'essaie de voir comment m'organiser au niveau de la RAM. j'en suis arrivé à cette conclusion:
Je sépare la RAM en 2 et je prends la seconde moitié (histoire de ne rien corrompre), donc pour moi elle commence à 0x88040000 (j'ai à peut près 256Ko de travail (?))
De là je vais utiliser la première partie de mon espace de travail pour y mettre mes processus (~128Ko pour les processus (?))
Le noyau va se trouver à l'adresse 0x88060000 (64Ko) et mes handlers à 0x88070000 (64Ko)

Pour l'instant le bootstrap ne fait pas grand-chose: un check du mpu et un début de loader ELF (il affiche juste l'header du fichier).
Sera-t-il vraiment nécessaire de compiler les programmes en Position Independent Executable car je pourrai le remapper comme je veux par la suite avec le loader non ?

En principe tu devrais le charger dans la RAM, mapper la zone appropriée dans P0, et le laisser en mode utilisateur. Mieux encore, tu peux mapper directement le programme de la ROM vers P0 (attention à la fragmentation dans le fs de la mémoire de stockage).

Pour loader directement depuis la ROM (ce qui me semble la meilleure idée) il faut que je réécrive un driver de lecture pour l'EEPROM, ce qui n'est pas encore d'actualité. (ou alors Bfile_* peut le faire pour moi ?)
Comment savoir où est mappé P0 ? je dois avouer n'avoir pas vraiment compris comment cette partie fonctionne.
Ça ne peut pas être des adresses physique car sinon il devrait y avoir des conflits avec P1 non ?
Puis même si le MMU mappe dans la RAM physique, comment il fait pour le pas écrire par-dessus mes handlers ou mon noyau (par exemple) ?

(La suite n'a pas grand-chose à voir avec le début du post)
Récemment j'ai réécrit un linker script (pour le bootstrap) et je me suis souvenu que tu m'avais dit:

D'abord si tu regardes bien la RAM statique (c'est ainsi qu'on appelle la zone ram) est à 08100000

pourtant récemment tu m'as dit:

Nope, c'est pas vraiment ça. La ROM et la RAM sont situées aux adresses physiques 0x00000000 et 0x08000000, respectivement.

Je peux dire dans mon linker que la RAM commence à 0x08000000 ? (ou j'ai encore rien compris ?)
(EDIT: dans la shout je t'ai demandé: la RAM de 0x00800000 à 0x00810000 c'est la RAM static ? >_<' sur le moment j'ai oublié que RAM = RAM static. Mais du coup je me demande comment sont gérées les variable static )
Lephenixnoir Hors ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 23/03/2019 18:40 | #


Je sépare la RAM en 2 et je prends la seconde moitié (histoire de ne rien corrompre), donc pour moi elle commence à 0x88040000 (j'ai à peut près 256Ko de travail (?))
De là je vais utiliser la première partie de mon espace de travail pour y mettre mes processus (~128Ko pour les processus (?))
Le noyau va se trouver à l'adresse 0x88060000 (64Ko) et mes handlers à 0x88070000 (64Ko)

Pas mal ! Tu as effectivement 256 ko de libre.

Pour les handlers, le premier est à 0x100, le troisième à 0x600 et a des événement numérotés jusqu'à 0x1000, mais tous commencent à 0x400. En supposant que tu utilises le numéro de l'événement comme un offset dans la zone VBR pour attaquer l'interruption (et que tu ne dépasses pas du dernier handler), tu n'as donc besoin que de 0x1100 = 4352 octets pour les handlers. Ne gâche pas un quart de ta RAM

Sera-t-il vraiment nécessaire de compiler les programmes en Position Independent Executable car je pourrai le remapper comme je veux par la suite avec le loader non ?

Si tu ne le compiles pas en PIE alors l'adresse utilisée dans le linker script sera définitive - tu ne pourras lancer le processus qu'à une seule adresse virtuelle. Si cette adresse est gérée par le MMU, ce n'est pas un problème, car tu peux la rediriger où tu veux. Si cette adresse n'est pas gérée par le MMU, c'est un problème car tu ne pourras pas faire ce que tu veux.

Sur les ordinateurs réels l'espace d'adressage est infini (64-bits) et tous les exécutables sont compilés en PIE pour pouvoir être chargé à des positions tirées aléatoirement (la technique s'appelle ASLR). Ça répond à un certain type d'attaques.

Comment savoir où est mappé P0 ? je dois avouer n'avoir pas vraiment compris comment cette partie fonctionne.

Il faut regarder dans le TLB. Le TLB contient une liste de mappings (adresse virtuelle, taille → adresse physique). La taille des pages ne peut pas être quelconque, sur SH3 c'est 1k ou 4k il me semble. Sur SH4 ça peut être plus. Attention le TLB ne peut contenir que 4×32 entrées (de mémoire toujours) donc il est strictement impossible de mapper tout P0 d'un coup. Il est également interdit de mapper la même adresse plusieurs fois (l'exception TLB Multihit sous SH4 te punit si tu le fais).

Ça ne peut pas être des adresses physique car sinon il devrait y avoir des conflits avec P1 non ?

Bonne remarque. C'est de la mémoire physique. Il n'y a pas de conflit car ce n'est pas un problème si plusieurs adresses virtuelles permettent d'accéder à la même mémoire physique. D'ailleurs c'est déjà le cas puisque tout ce qui commence par un 8 et tout ce qui commence par un a pointe au même endroit.

Puis même si le MMU qui mappe dans la RAM physique, comment il fait pour le pas écrire par-dessus mes handlers ou mon noyau (par exemple) ?

Le MMU peut très bien envoyer une page quelconque de P0 vers la zone de RAM physique où tes handlers sont stockées. Dans ce cas lire et écrire dans la zone mappée permettra d'accéder à tes handlers. C'est dangeureux !

Yatis a écrit :
Récemment j'ai réécrit un linker script (pour le bootstrap) et je me suis souvenu que tu m'avais dit:
D'abord si tu regardes bien la RAM statique (c'est ainsi qu'on appelle la zone ram) est à 08100000

pourtant récemment tu m'as dit:
Nope, c'est pas vraiment ça. La ROM et la RAM sont situées aux adresses physiques 0x00000000 et 0x08000000, respectivement

Attention. L'adresse 0x08100000 est une adresse virtuelle, qui est donc dans P0. Les deux autres adresses que j'ai données sont des adresses physiques. Il ne faut pas mélanger ces nombres.

La zone 0x08100000 est mappée par le système vers une partie de la RAM lorsqu'un add-in est lancé. Sous SH3, cette zone fait 8k. Sous SH4, elle fait 64k. Et elle est quelque part entre la mémoire principale, le tas et la pile dans les premiers 256k de RAM (ceux auxquels tu ne veux pas toucher, et à raison).

Je peux dire dans mon linker que la RAM commence à 0x08000000 ? (ou j'ai encore rien compris ?)

Le linker fonctionne en adresses virtuelles, donc si tu lui dis ça tu vas avoir potentiellement deux problèmes :
* L'adresse 0x08000000 de P0 n'est pas forcément mappée.
* Si elle l'est, elle ne pointe pas forcément sur la RAM.

Non, tu ferais mieux de lui dire qu'elle commence à 0x88000000, qui est une adresse virtuelle qui pointe toujours vers la RAM, car elle est dans P1, donc elle n'est pas gérée par le MMU. Je pense que ça doit commencer à être clair pour toi que P1 et P2 sont des vues sur la mémoire physique et que adresser dans P1/P2 ou dans la mémoire physique c'est pareil (à un 8 ou un a près au début de l'adresse).

(EDIT: dans la shout je t'ai demandé: la RAM de 0x00800000 à 0x00810000 c'est la RAM static ? >_<' sur le moment j'ai oublié que RAM = RAM static. Mais du coup je me demande comment sont gérées les variable static )

Attention au mot « statique » ici. Cette zone est appelée « RAM statique » parce que son adresse virtuelle dans P0 ne change jamais, alors que les adresses du tas et de la pile, qui sont exprimées depuis P1, changent entre les versions de l'OS. (D'ailleurs l'adresse physique vers laquelle elle pointe change aussi, mais ça ne se voit pas.)

Cela n'a rien à voir avec les variables static qui sont juste des symboles cachés aux autres fichiers (si déclarées à la racine du fichier) ou des variables donc la valeur persiste entre les appels d'une fonction (si déclarées dans une fonction) et vont souvent dans .data ou .bss. Le fait que ces deux sections soient chargées dans la RAM statique n'a aucun lien.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Yatis Hors ligne Membre Points: 581 Défis: 0 Message

Citer : Posté le 23/04/2019 22:29 | #


tu n'as donc besoin que de 0x1100 = 4352 octets pour les handlers. Ne gâche pas un quart de ta RAM

Surtout que j'avais oublié de prendre en compte mon File Systeme, donc je pense utiliser le dernier quart de la RAM pour stocker mes handlers ainsi que le kernel.
L'avant-dernier quart servira pour mon FS.


Si tu ne le compiles pas en PIE alors l'adresse utilisée dans le linker script sera définitive - tu ne pourras lancer le processus qu'à une seule adresse virtuelle. Si cette adresse est gérée par le MMU, ce n'est pas un problème, car tu peux la rediriger où tu veux. Si cette adresse n'est pas gérée par le MMU, c'est un problème car tu ne pourras pas faire ce que tu veux.

Dans le meilleur des mondes j'aimerais que le fichier ELF me donne chaque section basée sur l'adresse 0x00000000 comme ça ce n'est pas trop compliquer pour le remapper.
Il me semblait que de compiler avec -pie me donnais ce que je cherchais...mais il génère des sections .got.*, ainsi que beaucoup plus de program header et de sections. Je suppose que c'est ça qui me permet de relocaliser le programme ou je veux (?) mais je dois avouer ne pas trop savoir quoi faire avec tout ça.
Pour l'instant j'ai compilé un "Hello World" sans PIE juste en indiquant dans le linker de commencer à 0x00000000 mais je suppose que ça va planter (ou vite casser) quand le programme va demander un saut à une adresse bien précise.
Tu m'as dit de regarder le fichier sh3eb-elf/sh3eb-elf/lib/libscript/shelf.x mais à aucun moment le linker s'occupe des sections .got.* donc je ne sais pas trop quoi regarder (le section rela.got ?).
Au passage quel est la différence entre -pie et -fPIE ?


Actuellement je suis toujours sur le loader (car je n'ai pas énormément de temps pour ce projet) mais j'ai pu avancer un peu, même si j'ai quelque doute sur la manière dont je gère le fichier ELF. (du coup si tu peux m'aider je suis preneur).
Pour l'instant je check le file header, je gère l'encodage des données (MSB / LSB) et je vérifie toutes les données pour m'assurer que le programme est destiné à être sur la calto.
Ensuite je récupère tous les program header et j'additionne leur taille (p_memsz) pour allouer qu'une seule grosse page mémoire. Puis je copie tous les contenus de chaque program header dans la zone allouée en faisant: start_new_page_address + pheader.p_vaddr. (Je compte implémenter un mmap() très simpliste où on pourra protéger les zones en écriture / lecture / exécution).
Pour l'instant le boostrap envoie les infos de la page mémoire utilisée par le kernel même si la zone en question commence obligatoirement a l'adresse 0x88070000 et à une taille (fixe ?) de 0x7eeff.
Et...c'est tout.
Il me manque toute la partie des sections (et je ne sais pas comment mis prendre, lire beaucoup de doc je suppose. Mais avant j'aimerai savoir quel type de sections j'aurai à prendre en charge avec des programmes compilé en PIE).

Du coup est-ce que le boostrap doit jouer le rôle du crt0 pour le kernel ? (ça me paraît plus logique que ce soit au kernel de le faire pour lui-même et pour les processus. D'ailleurs Kristaba avait fait un linker dynamique si je ne m'abuse (je n'ai aucune idée du principe de fonctionnement d'un tel truc par contre mais je verrai plutard)).
Dois-je allouer, pour chaque processus, un espace en plus en guise de stack ? (ça me semble logique mais je préfère demander) (je pense laisser 8 ko ~ 32 ko de stack par processus). Le kernel utilisera la stack de Casio (même si je ne connais pas la taille de cette dernière) car j'aimerai gagner le plus de place possible dans P1.
Je ne suis pas trop à côté de la plaque ?


Sinon voila comment je compte m'organiser fois que le loader sera sur pied (et stable):
* Réorganiser toute l'architecture du noyau.
* Réorganiser mes handlers.
* Mettre en place brk() / sbrk() / malloc() / free() / mmap() / munmap().
* Faire un VFS pour avoir accès au FS de Casio et a mon FS. (en évitant de passer par BFile_*() donc ça risque de me prendre pas mal de temps de réécrire un driver (Read-Only pour l'instant) pour l'eeprom).
* Pouvoir lancer un processus via les fichiers ELF présent dans la SMEM. (en l'occurrence le premier processus sera le Shell)
* Mettre en place un scheduler.
* Faire un max de tests unitaires pour éviter le plus possible les fuites de mémoire.
* Clean le code.
* ... on verra si j'arrive à faire tout ça, mais je m'occuperai surement gérer la sécuriter du kernel.
Lephenixnoir Hors ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 23/04/2019 22:43 | #


Yatis a écrit :
Il me semblait que de compiler avec -pie me donnais ce que je cherchais...mais il génère des sections .got.*, ainsi que beaucoup plus de program header et de sections. Je suppose que c'est ça qui me permet de relocaliser le programme ou je veux (?) mais je dois avouer ne pas trop savoir quoi faire avec tout ça.

Essentiellement tu décides à quel endroit tu veux le mettre, ensuite tu remplis les sections .got.* qui contiennent des informations utilisées par le programme pour localiser les données que tu as chargées. Je reconnais ne pas en savoir beaucoup plus...

Pour l'instant j'ai compilé un "Hello World" sans PIE juste en indiquant dans le linker de commencer à 0x00000000 mais je suppose que ça va planter (ou vite casser) quand le programme va demander un saut à une adresse bien précise.

Surtout que si tu le mappes en 0 le pointeur nul risque de ne pas créer de segfault...

Tu m'as dit de regarder le fichier sh3eb-elf/sh3eb-elf/lib/libscript/shelf.x mais à aucun moment le linker s'occupe des sections .got.* donc je ne sais pas trop quoi regarder (le section rela.got ?).

Oui, c'est ça (rela est une abbréviation de "relocation"). Si tu veux les détails du chargement il faut voir dans la documentation de ld.so je suppose.

Au passage quel est la différence entre -pie et -fPIE ?

Le premier est une option de linker, le second une option de compilation. Si tu utilises le second quand tu compiles, tu dois aussi le passer au linker pour qu'il puisse faire les raccords. De façon générale, passe les flags de compilation au linker, ce qui aide parfois et peut poser des problèmes si tu ne le fais pas de toute façon (ie. libgcc).

Actuellement je suis toujours sur le loader (car je n'ai pas énormément de temps pour ce projet) mais j'ai pu avancer un peu, même si j'ai quelque doute sur la manière dont je gère le fichier ELF. (du coup si tu peux m'aider je suis preneur).

En fait oui, j'ai retrouvé la documentation dont je t'avais parlé. http://www.sco.com/developers/gabi/latest/contents.html

Puis je copie tous les contenus de chaque program header dans la zone allouée en faisant: start_new_page_address + pheader.p_vaddr. (Je compte implémenter un mmap() très simpliste où on pourra protéger les zones en écriture / lecture / exécution).

En général les adresses virtuelles vont ressembler à des choses comme 0x88001d00 donc tu n'as pas vraiment envie d'ajouter une adresse dessus. Je peux me tromper parce que je n'ai pas vérifié la sémantique de tous les champs avant d'écrire de commentaire, mais fait gaffe.

Il me manque toute la partie des sections (et je ne sais pas comment mis prendre, lire beaucoup de doc je suppose. Mais avant j'aimerai savoir quel type de sections j'aurai à prendre en charge avec des programmes compilé en PIE).

Tu ne t'occupes pas des sections pour autant que je sache, tu charges juste les programmes. Les sections sont juste un découpage plus fin que les programmes qui a une sémantique pour le format ELF, mais ça ne concerne pas le loader. D'ailleurs les programmes ont spécifiquements des flags de protection mémoire alors que les sections n'ont rien de vraiment équivalent.

Du coup est-ce que le boostrap doit jouer le rôle du crt0 pour le kernel ? (ça me paraît plus logique que ce soit au kernel de le faire pour lui-même et pour les processus. D'ailleurs Kristaba avait fait un linker dynamique si je ne m'abuse (je n'ai aucune idée du principe de fonctionnement d'un tel truc par contre mais je verrai plutard)).

Il faut bien que le kernel se charge. Mais il ne se charge pas pareil qu'un processus, il se met dans la mémoire à peu près où il veut (en principe dans la mémoire physique jusqu'à ce que la pagination soit activée, mais dans ton cas elle est en place dès le début) et ensuite il se mappe dans les espaces d'adressage de chaque processus (sauf KPTI).

Dois-je allouer, pour chaque processus, un espace en plus en guise de stack ? (ça me semble logique mais je préfère demander) (je pense laisser 8 ko ~ 32 ko de stack par processus).

En effet, ton processus a envie d'avoir une pile

* Mettre en place brk() / sbrk() / malloc() / free() / mmap() / munmap().

Tu auras certainement besoin de mmap()... pour implémenter brk().

Sinon ça m'a l'air de tenir la route, je ne vois pas de conneries immédiates dans l'ordre que tu présentes
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Yatis Hors ligne Membre Points: 581 Défis: 0 Message

Citer : Posté le 07/05/2019 22:24 | #


En général les adresses virtuelles vont ressembler à des choses comme 0x88001d00 donc tu n'as pas vraiment envie d'ajouter une adresse dessus. Je peux me tromper parce que je n'ai pas vérifié la sémantique de tous les champs avant d'écrire de commentaire, mais fait gaffe.

Surtout que si tu le mappes en 0 le pointeur nul risque de ne pas créer de segfault...

C'est pour ça que je link tout à l'adresse 0x00000000, pour tout mapper dans la nouvelle zone puis faire un new_page_address + entry pour lancer le processus, ça m'évite d'avoir des adresses bizarres chiantes à relocaliser, (et c'est ce que faisait Kristaba il me semble).


J'ai un peu de temps en ce moment pour continuer mon loader (qui commence à trainer dans la longueur).
Actuellement je suis confronté à 2 problèmes:
Le premier problème vient du fait que je n'arrive pas à écrire le linker pour les futures processus du noyau.
Je compile chaque fichier avec -fPIE puis le linkage se fait avec -pie. J'ai essayé de faire un linker script pour gérer toutes les nouvelles sections générées.
La compilation se passe bien, mais readelf -h m'indique une erreur:
* readelf: Error: Section 7 has invalid sh_entsize of 0000000000000004
* readelf: Error: (Using the expected size of 12 for the rest of this dump)

Et je n'arrive pas à trouver la source du problème dans le linker, je fais donc encore appelle à toi :

OUTPUT_ARCH(sh3)
ENTRY(_main)

MEMORY
{
    /* virtual memory, relative to the dynamic relocation start address */
    relative (rwx) : o = 0x00000000, l = 128k
}

PHDRS
{
    text PT_LOAD ;
    data PT_LOAD ;
}

SECTIONS
{
    .interp         : { *(.interp) }
    .hash           : { *(.hash) }
    .gnu.hash       : { *(.gnu.hash) }
    .dynsym         : { *(.dynsym) }
    .dynstr         : { *(.dynstr) }
    .gnu.version    : { *(.gnu.version) }
    .gnu.version_d  : { *(.gnu.version_d) }
    .gnu.version_r  : { *(.gnu.version_r) }
    .text    : {
        default_entry = . ;
        *(.text);
        *(.text.*);
    } : text

    .rodata    : {
        *(.rodata);
        *(.rodata.*);
    }

    .data    : {
        *(.plt);
        *(.data);
        *(.data.*);
    } : data
    .rela.got : {
        *(.got.plt);
        *(.got);
    }
    .bss    : {
        __bbss_start = . ;
        *(.bss);
        *(COMMON);
        __bss_end = . ;
    }

}



Deuxième problème: Le loader a un problème avec la lecture de fichier.
J'ai commencé à écrire un driver pour Bfile_readFile(), Bfile_openFile(), Bfile_closeFile() et Bfile_SeekFile(), histoire d'avoir un open(), read(), close(), lseek() et pouvoir débuguer avec mes meilleurs copains à savoir valgrind et gdb. (donc je les utilise toujours)
Mon problème et assez étrange, toute la partie vérification des headers fonctionne sur mon PC mais ne fonctionne pas sur la calto.
Pourtant j'arrive à lire et vérifier la partie e_ident[] mais tout le reste est décalé d'un ou plusieurs octet, certaines parties justes, d'autre non... (x_x)
Je pense que ça viens du Bfile_readFile() qui fonctionne pas, car (je le répète) le loader fonctionne sur mon laptop.

Du coup ce problème change mon planning:
* Je vais reprendre le bout de "noyau" que j'avais et le réécrire entièrement en me basant sur l'organisation en RAM que j'avais prévue.
* Je mets en place le VFS.
* J'écris un driver pour la SMEM. (au final il n'y a pas grand-chose à refaire: open() / close() / read() / lseek())
* Je finis le loader.
* Je sépare le Shell du kernel.
* Je mets en place l'ordonnanceur.
À moins que le problème du loader vienne d'autre part (mais ça m'étonnerai), je pense partir là-dessus.
Lephenixnoir Hors ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 07/05/2019 22:46 | #


Hmm, j'ai jamais linké d'exécutables en PIE donc je ne saurai pas forcément ici... >_>

Toutes tes sections devraient être associés à un programme (ie la clause :x après l'accolade) fermante, à moins qu'il y a une valeur par défaut. Je pense que c'est le cas même si les sections ne sont pas chargées, tu peux marquer le programme avec NOLOAD.

Mon problème et assez étrange, toute la partie vérification des headers fonctionne sur mon PC mais ne fonctionne pas sur la calto.

Je parie un contre dix que c'est un problème d'endianness.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Yatis Hors ligne Membre Points: 581 Défis: 0 Message

Citer : Posté le 15/07/2019 19:10 | #


Des news du projet (déjà 2 mois x_x ) !

J'ai tout repris de 0 depuis la dernière fois et ça a bien gagné en lisibilités / modularité / sécurité !
Je n'ai pas eu énormément de temps à consacrer au projet (fin d'année oblige) mais j'ai pu avancer ces dernières semaines et j'arrive au même point qu'il y a deux mois, sauf que là j'ai une vraie base solide

Alors, je préfère prévenir, il n'y a rien d'incroyable pour l'instant. J'ai juste une bonne base pour le kernel et il est actuellement développé pour "supporter plusieurs plateformes".
Tout repose sur les devices. Ce sont des fichiers qui permettent d'interagir avec l’hardware en utilisant une API. (open, read, et compagnie).
Donc actuellement le noyau peut gérer n'importe quel écran ou clavier du moment ou les drivers sont écrit et mis dans des devices.
Les devices (ainsi que les drivers) sont chargés dynamiquement au démarrage en fonction du hardware donc pas de risque d'avoir un /dev/display en couleur sur une monochrome.
J'ai aussi passé pas mal de temps de désassembler les handlers/syscalls de Casio pour comprendre comment ils ont géré le clavier et c'est très...spécial. (je vous laisse avec ma section de la Bible pour en juger).
Ce que j'avais en tête était simple : mettre en pause le CPU (arrêter de l'alimenter) et le réveiller uniquement quand l'utilisateur appuie sur une touche.
Et ça fonctionne, après plusieurs nuits à essayer de comprendre comment le clavier fonctionne, j'arrive enfin à gérer l'interruption du KEYSC (0xbe0) proprement !
Après, j'avoue que la partie "interprétation" des touches est super moche et lente x_x (ce n'est pas ce qu'il m'intéresse pour l'instant, je la referai à l'avenir).

Voilà ce que j'ai opté pour la gestion du clavier :
* [ALPHA] Passe de minuscule a majuscule. (vis et versa).
* [SHIFT] Permet d'afficher ce qu'il y a sur les touches (0~9, +, -, /, etc...)
* [(-)] Est utilisé comment touche contrôle (CTRL).
* [ARROW] Permet de déplacer le curseur.
(PS : On affiche toujours des caractères de base).
(PS(bis) : Le [CTRL] et prioritaire sur [SHIFT] qui est prioritaire sur [ALPHA]).

Le fait d'avoir des drivers bien à part du noyau va permettre de séparer le plus possible la partie "drivers" de la partie "noyau" et donc faciliter le portage du kernel.
(Et ça permet, aussi, d'hardcode en Asm les drivers pour gagner en efficacité !
Je le fais déjà pour le clavier (pas tout mais la gestion de l'interruption oui) et l'écran (T6K11). Ça fonctionne très bien !)

Pour résumer, voilà actuellement ce que j'ai :
* Un bootstrap qui load les drivers, les devices, les handlers en fonction du hardware.
* L'allocation dynamique de page ("physique") de 64 octets. (mais c'est pourri et temporaire, je compte changer ça plus tard).
* Un FS en RAM (tout basique mais c'est juste pour avoir les devices (/dev/display et /dev/tty0 par example)).
* un VFS pour pouvoir utiliser mon FS et celui de Casio "en même temps" et avoir une seul API de fichier.
* La gestion des devices : ça me permet d'avoir une grosse abstraction au niveau hardware, grâce au VFS.
* La gestion des TTYs \0/
* Le chargement / changement de fonts pour les TTYs.
* La configuration complete de INTC.
* Un gestionnaire d'interruption propre (similaire a gint: des block de 32 octets).
* Un driver pour l'écran (T6K11).
* Un driver pour le clavier (je gère les interruptions claviers !).
* Une structure au niveau de l'organisation du projet qui commence à être solide ! (enfin !).


La prochaine étape et encore "facile" pour moi car il s'agit des changements de contexte ainsi que la séparation complète entre le bootstrap et le kernel (il deviendra un add-in à part entière).
Les changements de contexte sont super-importants et faciles à mettre en place avec la structure actuelle du code donc je ne me fais pas de soucis avec cette partie.
L'intérêt de sortir le bootstrap du kernel serait d'avoir un seul noyau qui prend en charge toutes les machines (monochromes, prizm, etc.). Donc il faudra "juste" avoir le bon bootstrap pour la machine (g1a et g3a). Le noyau sera commun a tout le monde (de plus le format ELF permettra des techniques avancées lors du mappage).
Pour séparer le bootstrap, il faut que j'écrive un driver pour le FS de Casio et pour ça, pas le choix, il va falloir désassembler les Bfile_* de Casio (soit ça me prend littéralement 4 nuits a d'assembler, soit ça va me prendre plusieurs semaines).
Ensuite viendra l'update mon VFS pour pouvoir "mounter" les différents FS n'importe ou et y accéder rapidement / proprement. (car ce n'est pas possible actuellement).
Bien sûr pas d'écriture dans la SMEM car trop dangereux (et pas utile pour l'instant), il me faut juste quelques primitives open, read, close, lseek.
Bref ça risque d'être assez long, mais une fois mis en place je pourrais loader facilement le noyau (ainsi que lui passer un fichier de configuration) depuis la SMEM ! \0/


Une fois cette étape faites je vais m'atteler à THE partie qui me fait un peu peur car je n'ai aucune connaissance là-dessus : la gestion de la mémoire virtuelle.
J'ai commencé à lire la documentation du SH7724 certaines parties encore assez floues et j'ai du mal à comprendre comment tout ça fonctionne (j'ai juste zyeuté vite fait la documentation).
Bien sur, avant de toucher au MMU, je vais désassembler le bootstrap de Casio et voir comment il configure la Calculatrice et surtout le MMU (et regarder si je peux le configurer sans briquer la calto).
Par contre, à partir de ce moment-là, je déconseillerai à tout le monde d'utiliser le kernel à moins d'être sûr de savoir ce qu'il/elle fait car ce sera assez expérimental.
(Ceci dit, le repos Gitea n'est pas sur celui sur lequel je travaille. Mon repo est privé et je push sur Gitea uniquement les versions stable et "documenter" du noyau et le jour ou la mémoire virtuelle fonctionnera, il faudra : sois créer un topic spécial pour le kernel. Sois que je change/renomme ce topic (et franchement je n'ai pas envie, car il représente beaucoup pour moi )).


Quoi dire de plus... Ha oui : Faites un tour sur le repo Gitea ! Et aussi sur la Bible de PC car j'y mets toutes mes documentations/découvertes.
Si vous compiler le projet, ne vous attendez pas à grand chose: ça boot en affichant quelque log, on tombe sur le TTY1 et vous pouvez tester le clavier. (et un reset pour quitter :/ ).
Les sources ne sont pas documentées à fond, mais suffisamment pour comprendre le fonctionnement de certaines parties.
(Attention : l'architecture actuelle du code risque fortement de changer une fois le bootstrap sortie du noyau et, par conséquent, la documentation sera obsolète).


Au passage, j'hésite sur la licence que je vais utiliser pour le noyau. Je ne sais pas s'il est possible de la changer en cours de route mais je pense mettre quelque chose d'un peu restrictif au début puis le mettre dans le domaine public une fois qu'il sera mature et stable (donc surement du CC0 mais on n'en est absolument pas à ce stade).
Pour l'instant je pense partir sur la licence LGPL3.0 car c'est la seule à demander que chaque changement soit documenté sans être super-restrictif non plus.
Comme ça si jamais quelqu'un voudrai aider, ça ne va pas bloquer à ce niveau-là. (même si c'est actuellement un projet personnel, le jour ou la mémoire virtuelle sera géré, je compte ouvrir le développement à ceux qui veulent).


Info un peu osef, mais je pars en stage pendant 5 mois, ce qui risque de m'empêcher d'être aussi productif que ces dernières semaines.
Mais le projet représente énormément pour moi et je ne compte pas l'abandonner avant d'avoir GladOS et l'OS de Casio en duaboot sur ma calto (c't'une blague hein xD ).

(PS: la documentation ainsi que le repo devrai arriver incessamment sous peu, je n'ai pas eu le temps de finir la documentation mais elles arrivent !)
Lephenixnoir Hors ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 18/07/2019 14:53 | #


Yo ! Merci pour ce pâté. Pour faire les choses dans l'ordre, je crois que tu bénéficierais grandement d'un renommage de topic + réécriture du post principal et puis re-situer un peu le projet. Ma plus importante question est : où veux-tu aller ?

J'ai aussi passé pas mal de temps de désassembler les handlers/syscalls de Casio pour comprendre comment ils ont géré le clavier et c'est très...spécial. (je vous laisse avec ma section de la Bible pour en juger).

Merci pour ta documentation ! Ça m'a bien intéressé à lire. Je n'ai pas encore tout compris, mais ça va venir. Je crois que le plus important serait que tu explique ton protocole : qu'as-tu fait pour arriver à tes conclusions ?

Voilà ce que j'ai opté pour la gestion du clavier :
* [ALPHA] Passe de minuscule a majuscule. (vis et versa).
* [SHIFT] Permet d'afficher ce qu'il y a sur les touches (0~9, +, -, /, etc...)
* [(-)] Est utilisé comment touche contrôle (CTRL).
* [ARROW] Permet de déplacer le curseur.

Pourquoi si tôt ? Sous Linux le driver clavier produit des keycodes, Shift/Ctrl/etc inclus, et ensuite le logiciel au-dessus (typiquement le compositeur graphique ou le serveur X) se charge de fournir la keymap et de combiner les touches. Supposons que dans une application j'ai besoin d'une autre touche équivalente à Alt ?

(Et ça permet, aussi, d'hardcode en Asm les drivers pour gagner en efficacité !
Je le fais déjà pour le clavier (pas tout mais la gestion de l'interruption oui) et l'écran (T6K11). Ça fonctionne très bien !)

Je t'invite à regarder un peu en chiffres ce que tu gagnes parce que j'ai eu des surprises parfois... et l'assembleur c'est chiant à maintenir. xD

Pour résumer, voilà actuellement ce que j'ai :

C'est pas trop petit 64 octets pour des pages ? :o

Combien il prend de place en RAM ton FS ? Est-ce qu'il peut grandir ? Est-ce un arbre ? Y a-t-il des inodes avec des métadonnées ? Certaines de ces questions ont peut-être déjà eu une réponse avant.

La prochaine étape et encore "facile" pour moi car il s'agit des changements de contexte ainsi que la séparation complète entre le bootstrap et le kernel (il deviendra un add-in à part entière).

Les changements de contexte c'est pas trop facile d'habitude, enfin bon courage. T'as une table de processus déjà ?

Une fois cette étape faites je vais m'atteler à THE partie qui me fait un peu peur car je n'ai aucune connaissance là-dessus : la gestion de la mémoire virtuelle.

Ah donc non t'as pas de processus. Comment tu veux faire des changements de contexte alors ? ó_ó

Pour séparer le bootstrap, il faut que j'écrive un driver pour le FS de Casio et pour ça, pas le choix, il va falloir désassembler les Bfile_* de Casio (soit ça me prend littéralement 4 nuits a d'assembler, soit ça va me prendre plusieurs semaines).

Oh, documente-le dans ce cas ! Ça m'intéresse. J'envisage de bypasser des limites de Bfile en faisant toutes mes opérations dans la RAM avant de "commit" à la fin, car y'a trop de limitations à la con. Je suis encore en train d'étudier mentalement la faisabilité de la chose mais se passer de la lecture serait encore plus top. Vise bien ta version d'OS car les versions de Bfile diffèrent selon les Graph monochromes traditionnelles, la Graph 35+E II et la Grpah 90+E !

Bien sur, avant de toucher au MMU, je vais désassembler le bootstrap de Casio et voir comment il configure la Calculatrice et surtout le MMU (et regarder si je peux le configurer sans briquer la calto).

Pour t'aider, voici un résumé de tout ce que je sais sur le pourquoi du comment de modifier le MMU ou non.

1. SimLo recommande de ne pas toucher au TLB. Plus de détails ici : http://www.casiopeia.net/forum/viewtopic.php?f=11&t=1742

2. AHelper a un jour brické une Prizm en tentant d'implémenter un système de libs partagées pour gagner de la place en mémoire de stockage. Il changeait la configuration du MMU pour mapper différents fichiers à différents endroits. D'après l'histoire, un jour il a quitté l'add-in en oubliant de restaurer la configuration du MMU et la calculatrice est devenue inutilisable. Mon "analyse" est que le système ne pouvait pas démarrer avec la config de MMU qu'il avait laissée (par exemple crashait avant d'arriver au bout du boot), et donc il était incapable d'exécuter du code pour régler le problème.

3. Normalement les registres du MMU sont tous réinitialisés par le power-on reset (bouton RESET au dos de la calculatrice) mais le système pourrait supposer des trucs bizarres. À étudier en détail.

Au passage, j'hésite sur la licence que je vais utiliser pour le noyau. Je ne sais pas s'il est possible de la changer en cours de route mais je pense mettre quelque chose d'un peu restrictif au début puis le mettre dans le domaine public une fois qu'il sera mature et stable (donc surement du CC0 mais on n'en est absolument pas à ce stade).

Tu peux la changer en cours de route mais chaque release sous une certaine license reste sous cette license donc tu peux pas modifier rétroactivement.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Yatis Hors ligne Membre Points: 581 Défis: 0 Message

Citer : Posté le 20/07/2019 12:15 | #


Yo ! Merci pour ce pâté. Pour faire les choses dans l'ordre, je crois que tu bénéficierais grandement d'un renommage de topic + réécriture du post principal et puis re-situer un peu le projet. Ma plus importante question est : où veux-tu aller ?

Je compte refaire un topic (à part) plus tard car pour l'instant je n'ai rien de bien intéressant et le projet n'est pas assez mature en parler "sérieusement".
Ou je veux aller avec ce projet ? En fait j'aimerais faire un OS unix-like pour nos chères G85 (fx-9860) et dérivées, ainsi que pour la Prizm (fx-cg20).
"Par contre si vous avez envie d'un OS meilleurs que celui de Casio pour lancer des supers jeux en 3D, connecter votre calculatrice à Internet, ou que sais-je, ce n'est PAS le but premier du projet."
C'est ce qu'avait dit Kristaba il y a maintenant 6 ans, mais ça correspond très bien a ma visions du projet. Pour moi ce projet me permet d'apprendre (énormément) et le fait de bosser sur une machine dont la spécification est limitée est intéressant : ça apprend des techniques de rétro-ingénierie, ça permet d'être dans un état "d'exploration", intrigué par tout ce qu'on trouve et toujours prêt à découvrir une nouvelle horreur de Casio.
À part ça, les gros avantages d'avoir système d'exploitation UNIX-like sur calto, c'est la sécurité, la fiabilité, l'API (syscall) mise à disposition et l'abstraction du matériel. (en partant du principe que les syscall mis a disposition seront proche d'un UNIX standard). Après, tout dépend de l'implémentation, mais je pense que les fonctionnalités "secondaires" pourraient intéresser les développeurs (bibliothèque partagée, système de fichier unifié, portabilité entre les différents modèles, implémentation en interne de pilotes USB...), mais c'est loin d'être à l'ordre du jour. Aussi, le fait d'avoir un terminal pourrait être sympathique pour certains utilitaires, les développeurs qui ne programment pas encore sur Casio pourraient faire cette transition plus simplement car le système serait UNIX-like. (et pourquoi pas porter des applications déjà existante, à condition qu'elles soient vraiment légères ).



Merci pour ta documentation ! Ça m'a bien intéressé à lire. Je n'ai pas encore tout compris, mais ça va venir. Je crois que le plus important serait que tu expliques ton protocole : qu'as-tu fait pour arriver à tes conclusions ?

Je suis actuellement en train de mettre a jour les informations de la Bible car j'ai de nouvelle infos à propos du clavier et j'ai des parties de code que j'avais désassemblé que j'ai documenté.
Pour répondre a ta question, voilà comment je mis suis pris pour comprendre le fonctionnent du KEYSC:
I - définir un but.
L'objectif étais de pouvoir gérer l'interruption du clavier, et ainsi pouvoir faire "dormir" le CPU en attendant l'appuie sur une touche et éviter de scanné "a la main" le clavier comme tu le fais pour gint.
Le problème qu'on avait c'est que personne (a moins que d'avoir loupé quelque chose) n'avais réussi a "clear" le flag d'interruption du KEYSC (ce qui provoquais une boucle infinie dans nos handlers) et rendais impossible l'utilisation de ce dernier.
J'ai donc listé ce que je savais à propos du KEYSC:
* Casio utilise l'interruption du KEYSC pour fonctionner, donc ils clear forcément l'interruption du KEYSC quelque part.
* Le code d'interruption du clavier est 0xbe0.
* Les interruptions génère un saut a VBR + 0x600.
* Je sais récupère la VBR en passant par l'assembleur.

II - Rechercher.
Il m'a "juste" fallu "suivre" l'interruption a la main pour trouver l'endroit ou Casio gère le KEYSC.
Je suis d'abord tomber sur leurs gestionnaires d'interruptions et d'exceptions...bon...c'est...c'est très...heuu...je vous laisse avec la documentation sur la Bible pour que vous vous fassiez votre propre avis. xD
L'un des gros problèmes (à part d'être extrêmement mal foutue) c'est qu'ils passent leur temps à chercher des informations dans la RAM, notamment les adresses des différents handlers pour les interruptions (dont celui pour le KEYSC).
Il me fallait absolument de quoi désassembler la RAM rapidement et facilement...j'ai donc créer un utilitaire pour faire ça...oui ça a donnée Vhex (qui faut que je le mette a jours d'ailleurs).
Après avoir écrit un désassembleur, j'ai continué à suivre le code et jusqu'à tomber (rapidement) sur l'handler de Casio pour le KEYSC. Et autant vous dire que l'handler est...archi moche, lent, absolument pas intuitif et...extrêmement loooonnnng ! (x_x)
Mais la première étape étais faite, j'avais trouvé ce que j'étais venu chercher

III - Expérimenter et documenter ce qu'on voit/comprend.
Une fois l’handler sous la main il faut le désassembler, faire une première lecture du code en le découpant le code en "block" (généralement a chaque appelle d'une sous-routine (histoire d'y voir un peu plus claire)) puis on repasse le code a revue mais en commentant chaque ligne cette fois. Et au bout de plusieurs passage ça commence à se débloquer et on comprend de plus en plus ce que fait le code et ce qu'on lit.
Jusqu'au moment où il faut tester ce qu'on pense avoir compris et/ou pour comprendre les nouveaux registres qu'on vient de trouver (s’ils ne sont pas documenté). Moi par exemple, je me suis fait un environnement de test sur mon kernel ou j'affichais tous les registres du KEYSC et j'ai repris le code que je venais de désassembler pour voir comment il réagit de mon côté. Il m'a fallu pas mal de temps pour comprendre comment "clear" le flag d'interruptions du KEYSC (je vous laisse encore une fois avec la documentation de la Bible), mais sachez que c'est extrêmement pas intuitif xD
Une fois que j'avais trouvé ce que je cherchais (clear l'interruption) j'ai continué de tester, encore et encore en notant tout ce que je voyais / comprenais et a la fin j'ai réussi à piger la plupart des rôles / fonctionnements des registres du KEYSC, comme la configuration des interruptions ainsi que les informations générée par l'hardware pour savoir le type d'interruption il vient de se produire. Il me restait plus as faire une documentation au propre et la mettre a disposition sur la Bible, car ça aidera/intéressera sûrement des personnes

Honnêtement, c'est de loin la meilleure expérience que j'ai faite. J'ai appris énormément de chose et j'ai hâte de refaire ça avec le Bfile_* (le seul truc compliqué, c'est que je désassemble la nuit...de 23h a 5~6h du mat, ce qui n'est pas top niveau productivité xD )
Bien sur, je n'ai pas tout découvert (loin de la) mais j'ai réussie à avancer ; maintenant j'ai une bonne partie de l'architecture du KEYSC et j'arrive à faire ce que je voulais (mettre le CPU en sleep, toussa toussa).
J'ai aussi commencé à désassembler GetKeyWait() histoire de voir comment Casio configure le KEYSC et pourquoi (ça ne m'a pas beaucoup avancé mais je le posterai sur la Bible a l'occasion).
Bonus funfact : je me suis tromper la première fois que j'ai récupéré l'adresse du handler (KEYSC) de Casio, j'ai pris une autre adresse qui n'a rien à voir...et, coup de chance, je suis tombé sur un passage qui s'occupe de la gestion d'une interruption venant du KEYSC (visiblement cela ne viens pas de l'interruption 0xbe0, ou alors j'ai loupé quelque chose). Je soupçonne être l'handler d'une fonction genre KeyInject() car il fait appelle a des registres bien spécifique du KEYSC (que je ne les ai pas encore examiné car Casio ne s'occupe pas de ces registres là dans leur handler (0xbe0)). À creuser...



Pourquoi si tôt ? Sous Linux le driver clavier produit des keycodes, Shift/Ctrl/etc inclus, et ensuite le logiciel au-dessus (typiquement le compositeur graphique ou le serveur X) se charge de fournir la keymap et de combiner les touches. Supposons que dans une application j'ai besoin d'une autre touche équivalente à Alt ?

Mon driver produit uniquement des keycodes ! J'ai juste une couche logicielle au dessus pour récupérer et interpréter les informations du driver.
Il me fallait absolument la gestion des touches pour, plus tard, tester les changements de contexte et aussi pour pouvoir déboguer plus facilement
Ceci-dit ça ma permis de juger la difficulté pour ajouter des couches logiciel au kernel, ce qui est assez facile finalement :o (j'ai remarqué quelque souci avec les TTYs mais la partie driver/logiciel est biens séparé et indépendante.)
Puis comme j'étais partie pour la gestion des keycode je me suis dit "quitte a commencé à faire un truc avec le clavier...autant s'marrer et voir à quoi ça peut ressembler xD", mais c'est vrai que c'était absolument pas le moment.
(ps: Je compte reprendre tout le projet de 0 quand j'arriverai a la gestion du la mémoire virtuel et des processus, histoire d'avoir une base solide et propre (l'architecture du noyau risque de fortement changer) )



C'est pas trop petit 64 octets pour des pages ? :o

Combien il prend de place en RAM ton FS ? Est-ce qu'il peut grandir ? Est-ce un arbre ? Y a-t-il des inodes avec des métadonnées ? Certaines de ces questions ont peut-être déjà eu une réponse avant.

Mmmmm...non, la taille ne pause pas de problème en particulier. Mais c'est vraiment pourrie comme système, vivement que je puisse gérer le MMU pour avoir un quelque chose de propre de ce côté (et on pourra parler de "vrai" page).

En ce qui concerne mon FS il est, comme je l'ai dit super basique et probablement mal penser pour le moment.
Mon FS se hiérarchise via des arbres binaire. À chaque étage, tous les fichiers sont stockés dans un arbre binaire qui les tries selon leur nom (pour l'instant) ; bien sur, chaque dossier contient un autre étage, donc un arbre binaire.
Les inodes sont ce qu'ont les FS ont en commun, grosso modo les données d'un fichier : la taille, son type, les droits d'accès, le nombre de liens, etc... (d'ailleurs cette partie est super mal foutue, j'aimerais utiliser une table de hachage pour avoir quelque chose d'un minimum propre, comme Kristaba faisais).
Le VFS quant a lui, s'occupe juste d'appeler des primitives comme "find_next_sibling()", "find_root_inode", "find_parent()", etc.
Donc voilà, rien de bien poussé pour l'instant et c'est sur quoi je vais travailler les prochains mois x_x.



Ah donc non t'as pas de processus. Comment tu veux faire des changements de contexte alors ? ó_ó

Casio -> kernel -> Casio ? (Me serai-je encore gouré de nom ? ).
Oui pour l'instant je n'ai pas de processus, d'ailleurs il va se passer un grand moment avant que de les implémenter xD



Oh, documente-le dans ce cas ! Ça m'intéresse. J'envisage de bypasser des limites de Bfile en faisant toutes mes opérations dans la RAM avant de "commit" à la fin, car y'a trop de limitations à la con. Je suis encore en train d'étudier mentalement la faisabilité de la chose mais se passer de la lecture serait encore plus top. Vise bien ta version d'OS car les versions de Bfile diffèrent selon les Graph monochromes traditionnelles, la Graph 35+E II et la Grpah 90+E !

Je sais que les Bfile_* sont différent en fonction des OS mais actuellement je n'ai qu'une 35++ en 02.05.2201, donc je vais commencer par lui. (de toute façons je suspecte Casio d'avoir son système de fichier moisi dans tout les OS (saut les récentes) ; ce qui va changer ce sera la façon de lire dans la ROM (je pense)).
Pour l'instant je n'ai rien commencer car je n'ai ABSOLUMENT plus de temps pour moi (et je n'ai pas la tête a ça pour l'instant).
Ceci-dit il faut que je finisse de documenter le clavier avant de commencer quoique ce sois (il me reste pas mal de chose, je vais sûrement finir ça ce weekend) x_x.



Normalement les registres du MMU sont tous réinitialisés par le power-on reset (bouton RESET au dos de la calculatrice) mais le système pourrait supposer des trucs bizarres. À étudier en détail.

Merci pour toutes ses informations, je les lirai quand je trouverai le temps x______x
Je compte désassembler le bootstrap / bootloader de Casio et être sûr que tous les registres sont initialiser correctement avant de toucher au MMU (je le répète mais il va se passer un graaaaaaand moment avant que j'y touche, mais j'ai hâte ; c'est une partie que m'est complètement inconnue ).
Lephenixnoir Hors ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 20/07/2019 13:36 | #


Je compte refaire un topic (à part) plus tard car pour l'instant je n'ai rien de bien intéressant et le projet n'est pas assez mature en parler "sérieusement".

Tu ne devrais pas attendre si longtemps, il y a des gens intéressés et tu as vu toutes les questions qui t'ont été posées l'autre jour !

Ou je veux aller avec ce projet ? En fait j'aimerais faire un OS unix-like pour nos chères G85 (fx-9860) et dérivées, ainsi que pour la Prizm (fx-cg20).

Super ! Un OS en ROM qui remplace celui de Casio à l'exception du bootcode ? Un OS avec un bootloader custom ? Un OS uniquement en RAM ?

L'objectif étais de pouvoir gérer l'interruption du clavier, et ainsi pouvoir faire "dormir" le CPU en attendant l'appuie sur une touche et éviter de scanné "a la main" le clavier comme tu le fais pour gint.

Oui, l'autre raison étant qu'en fait pour générer des répétitions régulièrement pour l'instant on est obligés d'avoir un timer... donc j'ai peur que ce soit pas gagné pour intégrer 0xbe0. /o\

Il me fallait absolument de quoi désassembler la RAM rapidement et facilement...j'ai donc créer un utilitaire pour faire ça...oui ça a donnée Vhex (qui faut que je le mette a jours d'ailleurs).

Dans fxos j'ai un plan (et des options de ligne de commandes) pour charger des dumps de la RAM pour faire ça. L'idée étant que tu peux en charger plusieurs pris dans différentes contextes (voire calculatrices) et comparer les données. Je l'ai pas implémenté toutefois...

Une fois l’handler sous la main il faut le désassembler, faire une première lecture du code en le découpant le code en "block" (...)

Sache que ça correspond à peu près à la notion de "bloc basique" en compilation donc le terme n'est pas anodin. Bien joué

Mon driver produit uniquement des keycodes ! J'ai juste une couche logicielle au dessus pour récupérer et interpréter les informations du driver.

Mais du coup c'est fait par qui ? Ici le responsable devrait être le TTY right.

En ce qui concerne mon FS il est, comme je l'ai dit super basique et probablement mal penser pour le moment.
Mon FS se hiérarchise via des arbres binaire.

.... rassure-toi il aurait pu être plus mal pensé ! xD (#FAT)

Casio -> kernel -> Casio ? (Me serai-je encore gouré de nom ? ).
Oui pour l'instant je n'ai pas de processus, d'ailleurs il va se passer un grand moment avant que de les implémenter xD

Le terme complet (commutation de contexte) désigne le moment où l'ordonnanceur décide d'exécuter un autre processus et où il faut donc sauvegarder le contexte du processus en cours puis charger celui du nouveau processus. Aussi, le moment où un syscall est appelé et on retourne en mode noyau.

Donc je suppose que c'est pas la meilleure expression à employer ici, mais je vois ce que tu veux dire. Comment tu fais pour revenir dans l'OS Casio actuellement ? Qu'est-ce que tu veux obtenir comme résultat in fine ?

Je sais que les Bfile_* sont différent en fonction des OS mais actuellement je n'ai qu'une 35++ en 02.05.2201, donc je vais commencer par lui. (de toute façons je suspecte Casio d'avoir son système de fichier moisi dans tout les OS (saut les récentes) ; ce qui va changer ce sera la façon de lire dans la ROM (je pense)).

Ça va être la dèche ça, je verrai si je peux désassembler celui de la Graph 35+E II parce que les syscalls ne marchent plus du tout (rien que créer, ouvrir, remplir et fermer un fichier fait des crashs 3 fois sur 4 chez moi).

Je compte désassembler le bootstrap / bootloader de Casio et être sûr que tous les registres sont initialiser correctement avant de toucher au MMU (je le répète mais il va se passer un graaaaaaand moment avant que j'y touche, mais j'ai hâte ; c'est une partie que m'est complètement inconnue ).

Si une collab' te paraît envisageable ici ce serait avec plaisir, j'ai commencé des bouts un peu chiants.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Yatis Hors ligne Membre Points: 581 Défis: 0 Message

Citer : Posté le 20/07/2019 14:45 | #


Oui, l'autre raison étant qu'en fait pour générer des répétitions régulièrement pour l'instant on est obligés d'avoir un timer... donc j'ai peur que ce soit pas gagné pour intégrer 0xbe0. /o\

Mais ?! Tu es au courant qu'on peut paramétrer un truc pareil avec le KEYSC ? xD
D'ailleurs faudrait que je teste ça a l'occasion...histoire d'être sûr de moi. (mais je sais qu'on peut avoir des interruptions pendant l'appuie d'une ou plusieurs touches et qu'on peut régler facilement le délai entre chaque interruption )

Super ! Un OS en ROM qui remplace celui de Casio à l'exception du bootcode ? Un OS avec un bootloader custom ? Un OS uniquement en RAM ?

Mon rêve serait d'avoir un bootloader custom qui permettrai de choisir entre l'OS de Casio et mon OS. Mais je n'ai aucune idée de comment faire (et ce n'est pas le moment de faire ça xD ). Mais bon, avant d'en arriver la, il y a quelque partie super critique à faire avant :
* La gestion du MMU en mode Multiple Virtual Memory.
* L'écriture dans l'EEPROM. (sans parler de la cohabitation de deux (voir plus) FS différentes >_< )
Une fois que l'écriture dans l'EEPROM sera sécurisé à 100 %, on pourra reparler du bootloader custom xD

Dans fxos j'ai un plan (et des options de ligne de commandes) pour charger des dumps de la RAM pour faire ça. L'idée étant que tu peux en charger plusieurs pris dans différentes contextes (voire calculatrices) et comparer les données. Je l'ai pas implémenté toutefois...

Ho ! :o ça pourrait être intéressant en effet ! Mais actuellement je préfère voir directement ce que fait Casio dans RAM.

Tu ne devrais pas attendre si longtemps, il y a des gens intéressés et tu as vu toutes les questions qui t'ont été posées l'autre jour !

Je ferrais un topic dédié au projet mais pas avant janvier 2020 (mon stage me permet pas d'avoir énormément de temps libre pour dev, je verrai donc une fois qu'il sera fini (dans 5 mois donc) :/ ). D'ici la, j'espère avoir un bootstrap correct ainsi qu'un VFS solide ! Parce que la, je n'ai rien à montrer et je n'ai envie de lancer de fausse joie.

Donc je suppose que c'est pas la meilleure expression à employer ici, mais je vois ce que tu veux dire. Comment tu fais pour revenir dans l'OS Casio actuellement ? Qu'est-ce que tu veux obtenir comme résultat in fine ?

Actuellement je ne rends pas la main au système, ce n'étais pas le but de cette version mais je m'en occupe rapidement !
Comme résultat à court terme, rendre la main au système proprement.
Comme résultat à long terme, avoir un bootloader custom

Ça va être la dèche ça, je verrai si je peux désassembler celui de la Graph 35+E II parce que les syscalls ne marchent plus du tout (rien que créer, ouvrir, remplir et fermer un fichier fait des crashs 3 fois sur 4 chez moi).

Ha ! Pourtant quand tu utilises l'add-in python, la création de fichier fonctionne ? Si ça fonctionne ça signifierai que leurs prototypes ont changé non ?

Si une collab' te paraît envisageable ici ce serait avec plaisir, j'ai commencé des bouts un peu chiants.

Bien sur !! Mais pour l'instant j'aimerais m'occuper des Bfile_* et de mon bootstrap :/
Lephenixnoir Hors ligne Administrateur Points: 24572 Défis: 170 Message

Citer : Posté le 20/07/2019 15:26 | #


Mais ?! Tu es au courant qu'on peut paramétrer un truc pareil avec le KEYSC ? xD

Eh bien... en fait non ! J'ai lu ta doc mais pas vu ça. Et tu sais que tu en sais plus que moi sur le KEYSC

Fais attention au bootloader. Pour rappel, c'est le premier ou les quelques premiers secteurs de la ROM. Tant que tu as le bootloader tu peux utiliser l'outil de mise à jour du système de Casio. Si tu l'écrases et que tu te plantes, la calculatrice est fichue car on n'a pas d'interface de programmation externe. Si tu veux un dual-boot mon conseil serait peut-être plutôt...

1. Garder le bootloader de Casio
2. Écraser ou déplacer le début de l'OS de Casio mais être capable de le lancer
3. Démarrer sur ton OS et insérer dans ton OS de quoi lancer celui de Casio

Parce que faire un bootloader qui marche est certainement très dur, mais du premier coup c'est un deal breaker.

Ha ! Pourtant quand tu utilises l'add-in python, la création de fichier fonctionne ? Si ça fonctionne ça signifierai que leurs prototypes ont changé non ?

Bien sûr le système de fichiers marche, mais il faut redocumenter les syscalls. Il y a des trucs qu'on ne connaît pas et actuellement on ne sait quasiment rien faire avec le FS.

Bien sur !! Mais pour l'instant j'aimerais m'occuper des Bfile_* et de mon bootstrap :/

Super, c'est très sympa o/
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Précédente 1, 2, 3, 4, 5, 6

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 56 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd