Dock version 0.1 (boite à icones pour lancer des app)

janvier 22, 2007

Voici la première version du dock pour menuet.

ce programme fonctionne comme le tracker, mis à part qu’il n’y a pas de nom mais des icones, et pas de sous menu.

le fichier de config est comme pour le tracker, on écris le nombre d’app, et pour chaque app, on crée une structure programme. au lieu d’écrire le nom du programme, on écris le nom du fichier icone à afficher.

dock.zip

à faire:

- modifier pour que la config est un fichier pur texte

- optimiser le code


Tracker Version 0.1

janvier 21, 2007

1) introduction

tracker est un lanceur d’application pour MenuetOS ont apparence est similaire au tracker de BeOS.
Il se présente sous la forme du boite à bouton. chacun d’eux ouvre un menu résentant les probrammes à lancer.

2) fonctionnement:

la configuration se trouve dans un fichier binaire don le format est comme suit:

dd nombre_de_menu
menu1 menuitem ‘texte du menu1′
menu2 menuitem ‘texte du menu1′

dd nombre_de_prog_du_menu_n
prog_N.X programme ‘texte du programme X’,'commande_du_programme_X’

  • menuitem est une chaine de 60 caractères
  • programme sont deux chaines de 60 caractères (60 pour le nom, 60 pour la command)

pour chaque chaine de caractères de menuitem et programme, les bytes 0 sont ajoutés pour ompléter l’espace restant

en analysant le fichier source de la configuration (cfgfile.asm) vous comprendrez mieux

attention!!! il faut être vigilant à ne pas faire d’erreur dans la configuration sinon le programme plante

3) liste des fichiers

  • cfgfile.asm ;source de la configuration
  • cfgfile.inc ;fichier inclus dans la source de la config
  • tracker.asm ;source du programme principal
  • tmenu.asm ;source du programme de sous menu
  • parser.inc ;fichier inclus dans la source des programmes
  • meos.inc ;fichier inclus dans la source des programmes
  • tracker.dat ;fichier de configuration
  • @tracker ;binaire du programme principal
  • @tmenu ;binaire du sous menu
  • build.bat ;script de conpilation et d’installation
  • readme.txt ;fichier d’informations

4) installation

lancer “build.bat” depuis msdos ou windows ou alors:

a) compiler les sources

tracker.asm => @tracker
tmenu.asm => @tmenu
cfgfile.asm => tracker.dat

b) copier les fichiers compilés
tracker.dat => “c:\kolibri\etc\tracker.dat” (“/hd0/1/kolibri/etc/tracker.dat”)
@tracker => “c:\kolibri\bin\@tracker” (“/hd0/1/kolibri/bin/@tracker”)
@tmenu => “c:\kolibri\bin\@tmenu” (“/hd0/1/kolibri/bin/@tmenu”)

5) A faire

  • a) Include un logo à afficher en tête de la boîte à boutons
  • b) Modifier le parser afin de pouvoir lire la config d’un fichier pure texte
  • c) faire en sorte que le sous menu à afficher sois passé en paramètre pluto que d’être inscrit dans un fichier temporaire
  • d) mettre tmenu comme thread du programme principal (un seul binaire pour l’ensemble)

tracker.zip


Librairie Dynamique

janvier 16, 2007

Voici la nouvelle version de mes librairies dynamiques.

Maintenant, vous rechercher l’adresse d’une fonction grâce à son nom (chaine de caractère au forma ascii)

Le nom des fonction est:

macro dlopen path : path est le chemin vers la librairie à charger
elle renvoie dans la pile le handler de la librairie (pointeur vers la zone chargée)

macro dlclose handler: handler est le handler (adresse) d’une librairie déjà chargée

macro dlsym handler,symbol : handler est le pointeur de la librairie et symbol est un pointeur vers le nom de la fonction dans le programme

pour charger une lib vous faite:

dlpath db ‘/hd0/1/kolibri/lib/mylib.mdl’,0
sym_fonction1 db ‘fonction1′ ,0
dlhandler dd 0
fonction1 dd 0

dlopen dlpath
pop [dlhandler]
dlsym [dlhandler], sym_fonction1
pop [fonction1]

;eventuellement
;push [param1]

call [fonction1]

la structure des lib est comme suite:

org adresse
dd adresse
dd sym_fn_1 , fn_1
dd sym_fn_2, fn_2
dd 0

fn_1:

ret

fn_2:

ret

;le programme trouve l’adresse d’une fonction en comparant la chaine de caractère pointée ;pointeur dans le programme (paramètre de la macro) avec chacunes de celles pointées ;dans l’antête de la lib jusqu’à avoir trouvé la correspondance où être arrivé à la fin de ;l’en-tête (indiqué par un zero)

;char** chaine1 = handler+(8*numero)-4 donc

mov [numero],1

debut_boucle:

mov eax,handler
mov ebx,[numero]
shl ebx,3
sub ebx,4
add eax,ebx

cmp [eax] ,0 ;si on est tombé sur un zero alors c’est la fin du tableau
jna calerror ;on a pas trouve de correspondance

mov esi,[eax] ;l’adresse est mise dans esi
mov edi,symbol
mov ecx,[strlen] ;strlen a été calculé plus tod dans la macro
repe cmpsb
jnz suivant
jmp trouve

suivant:

inc numero
jmp debut_boucle

;une fois le nom trouvé, on a le numéro corespondant (= le compteur)

mov eax,handler
mov ebx,[numero]
shl ebx,3
add eax,ebx

push [eax] ;on sauve le resultat dans la pile
jmp fin

callerror:

push [0] ;on renvoie la valeur null dans la pille

fin:

mdl4.zip (programme d’exemple de cette nouvelle librairie)

ipc3. zip (Programme de démo pour l’utilisation de l’IPC avec la denière version de la librairie

nouvelle version:

  • Les adresses des fonctions sont exportées au moment du chargement de la librairie (avec la macro “dl_load ‘fichier’, table d’export; en utilisant les symboles (chaine de caractères pour nomer la fonction));
  • pour appeler une fonction, vous pouvez utiliser “dllcal [fonction],[valeur de retour],parm1,…,param4; (la macro va automatiquement placer les paramètres dans la pile et enregistrer la valeur de retour)
  • la fonction dl_load est améliorée, on ne charge que 2 fois le fichier, et lors de la première fois, le buffer est automatiquement updaté; les variables sont des adresses (fileinfo eq 0×1000 et dbid eq 0×1100 au lieu de “dd”); ça a réduit d’autant la taille du fichier exécutable

ipc4.zip


Pilotes de type serveur (à la manière de QNX)

novembre 22, 2006

Voici ma dernière idée que je m’empresse d’écrire avant de l’oublier.

En réfléchissant à la manière d’implémenter des pilotes en mode utilisateurs pour KolibriOS (Menuetos), je constatatait plusieurs problèmes:

  • Comment faire pour que le programme sache avec quel programme(le pilote) il doit communiquer pour utiliser le matériel.
  • Si au lieu d’utiliser des pilotes mais en utilisant des librairies dynamique contenant le pilote, comment le programme saurait-il quel module charger.

Il y a bien entendu d’autre problèmes qui seraient mis en évidence, mais ceux là me semble assez conséquent. J’imagine bien que le développeur de microsoft windows, ou des systèmes linux unix rieraient bien en lisant cela, mais leur système est aussi bien plus mature que Kolibri, et ces problèmes là on été résolut depuis le début. Du fait de la conception même de MenuetOS, il va faloir beaucoup réfléchir afin de parvenir à un système de pilote efficace, sans boulversser le fonctionnement même du système d’exploitation (pour des raison de compatibilité assendante et dessendante notament)

En pensent à la conception de Menuet, j’ai réalisé que la couche réseau était déjà bien avancée, et me suis dit qu’elle pourai être utilisée.

Le système est relativement simple:

  • Dans linux pour sortir du son de la carte son, on écrit dans /dev/audio ou un truc dans le genre, le pilote reçoit alors ce qui a été écrit dans ce “fichier spécial”. comme lorsque vous tapez “cat fichier.wav /dev/audio”, vous entendrez alors le fichier joué.
  • Dans menuet il n’y a pas de système de devfs pour faire ce genre de manipulation, mais un sytèm, qui est à la base du fonctionement des réseau et disponible permet de faire semblable

Ce système est les socket:

  • Lorsque un programme voudra lire un fichier .wav. il va charger le fichier en mémoire, et copier le contenu dans le socket.
  • Le serveur va alor voir qu’il y a des information (le son) qui rentre dans le socket, et va faire le nécessaire pour transmettre les ordres à la carte son

Pour réaliser celà, au lieu d’écrire dans un fichier conventionnel, on va écrire dans un socket identifié par un numéro de port (conventionnel, par exemple, la sortie audio dans le port 6000, l’entrée audio dans le port 6005)

Le serveur lui pourai charger le pilote pour gérer le matériel depuis la ligne de commande comme dans QNX, pour utiliser une carte son du modèle ac97 on fait : “ioaudio -d ac97 ” ça veux dire qu’on lance le serveur qui est un exécutable, et on lui dit quel pilote utiliser , ac97 en l’occurence”, le serveur va alor démarrer, charcher le fichier pilote (dynamiquement) et créer un lien dans devfs.

Dans MenuetOS on pourait fair un truc du genre, on exécute la commande “ioaudio” avec “ac97″ en paramètre, et le programme “ioaudio” se lencerai, et chargerait “ac97.drv” , et ouvrirait le port num UNTEL (convenctionné)
et se mettra en attente (mode listen) le temps qu’il reçoi la connection d’un client, lorsqu’une connection est établie, il lira les information qui seront entrée et les envera vers la carte son, grâce au code du pilote.

Du coté client, on a pas besoin de se soucier du pilote avec le quel communiquer, du module à charger, mais on écrira simplement les info dans le socket une fois la connection établie.


L’Assembleur Orienté Objet

septembre 6, 2006

Vous vous demandez certainement ce que c’est cette histoire, de l’assembleur orienté objet.

Ce principe permet de combiner les avantages du langage d’assemblage et des langages plus évolués (dit orienté objets) tels que le c++.

Dans l’assembleur, il n’y a pas de variables; juste des pointeurs donnant l’adresse d’une zone présise d’une taille précise (exemple : texte db ‘ceci est un text’, dans ce cas, “texte” n’est pas une chaine de caractère, mais juste l’adresse de celle-ci)

avec fasm, il est possible de créer des structures contenant plusieurs données exemple:

struc mystructure
{
nombre1 dd 0
nombre2 dd 0
}

mais nous pouvons aussi lui attribuer des valleurs par paramètres; exemple:

struc mystruc2 val1,val2
{
nombre1 dd val1
nombre2 dd val2
}

ensuite il suffit de de créer des variables de ce “type” :
mavar1 mystruc
mavar2 mystruc2 10,30

pour accéder aux valeurs nous utilisons, comme en C, les points:

mavar1.nombre1 => contient le doublemot (dd) 0
mavar1.nombre2 => contient le doublemot (dd) 0

mavar2.nombre1 => contient le doublemot (dd) 10
mavar2.nombre2 => contient le doublemot (dd) 30

Ce n’est pas tout.
une structure permet aussi d’insérer du code comme par exemple

struc mastructure param1
{
val1 dd param1

fonction1:
code de la fonction
ret
}

lorsque vous auré défini une variable de ce type:
variable mastructure param1

vous pourez accéder à ses valeurs:
variable.var1

ou a ses fonction:
call variable.fonction1

nous avons ainsi défini les variables et les méthodes des objet, typiquement comme en orienté objet

xinput.zip

ce fichier montre comment créer une boite de texte et manipuler celle ci grace à une structure “textbox” contenant des variables , et les méthodes “draw” et “input” :

fichier:
test.asm => source principale
input.inc => définition de la structure
meos.inc => fonctions relatives à menuet (macro pour l’utilisation des syscalls)
test => fichier compilé

le programme se compile avec fasm


Projet: Cd d’installation de Kolibri( version hd avec grub)

août 24, 2006

Bon, je sais que ça a l’air un peut gros comme projet…

mais je pense que c’est faisable.

le but est simple: obtenir un cd bootable qui installe menuet os sur le disque dûr, avec un minimum d’intervention de l’utilisateur.

Bien entendu l’instalation devra se faire “self-hosted” (depuis un système menuetos).

Pour ça, il sufirait de créer une disquette de boot, avec le système de base; et les fichiers à copier se trouvent sur le cdrom.

grâce à la fonction 70,on peux copier depuis un cdrom.

pour faire voici les étapes:

  • - démarage du système
  • - lancement du programme d’instalation
    • détection des disques
    • détection du lecteur cdrom (soit par question à l’utilisateur, soit par lecture d’un fichier précis sur le cdrom)
  • création des réperoitres de base: /HD0/1/KOLIBRI et /HD0/1/KOLIBRI/BOOT
  • copie des fichier systèmes:
    • /hd0/1/KOLIBRI/menuet.img;
    • /hd0/1/KOLIBRI/BOOT/STAGE1
    • /hd0/1/KOLIBRI/BOOT/STAGE2
    • /hd0/1/KOLIBRI/BOOT/MENU.LST
    • /hd0/1/KOLIBRI/BOOT/MTLDR
    • /hd0/1/KOLIBRI/BOOT/hdkernel.mnt
  • puis on demande s’il faut installer des prog suplémentaires (comme les jeux, les app diverse et les sources, on crée les répertoires nécessaires, et on copie les fichiers)
  • on redémare le système (toujours avec le cdrom) et au boot on choisis dans le menu “install grub”,pour installer grub dans le mbr puis on peux redémarer sans le cd.

Bien entendu, les fichiers peuvent être compressés pour gagner en place, et pour cela, il faudrai adapter l’algorythme de “mhc” pour l’usage de la fonction 70, et l’inclure dans le programme d’installation.

je vais essayer de faire un ptit cd d’installation, et vous en dirai des nouvelles (dès qu’il est fini, j’ajoute le lien qu’il faut, et j’averti la comunauté de kolibri dans les forums.

Lisez la suite de cette entrée »


Comment copier un fichier avec la fonction 70 de kolibri

août 16, 2006

0) On a comme variables:

src db ‘/chemin/vers/le/fichier_source.ext’,0
dst db ‘/chemin/vers/le/fichier_destination.ext’,0

note: le chemin doit correspondre à la nouvelle norme de kolibri:

/hdx/y/
/cdx/y/
/fd/y
/rd/Y

x étant le disque(de 0 à 3) et y la partition (à partir de 1)
fileinfo:

.subfunct    dd 0×0 ; numero de la fonction
.position     dd 0×0 ; debut à lire
.reserved    dd 0×0 ; reserve
.bytes        dd 0×0 ; taille à lire
.buffer        dd 0×0 ; les données seron écrite ici
.blank         db 0 ; resté vide
.ptr_path    dd 0×0 ; adresse du fichier

dbid:

.attribut     dd 0×0
.datatype   db 0
.reserved   db 0,0,0
.creatime   db 0,0,0,0
.creadate   db 0,0,0,0
.accestim   db 0,0,0,0
.accesdat   db 0,0,0,0
.modiftim   db 0,0,0,0
.modifdat   db 0,0,0,0
.filesize      db 0×0,0×0

1) obenir les info du fichier source par la fonction 70 ,5

mov [fileinfo.subfunct],0×5 ; on spécifie la subfonction 5
mov [fileinfo.buffer],dbid ; on indique où les info son écrites
mov [fileinfo.ptr_path],src ; l’adresse vers le nom du fichier

mov eax,70
mov ebx,fileinfo
int 0×40

les info son enrgistré dans la structure spécifiée (dbid)

2) On applique les info pour charger le fichier

mov [fileinfo.subfunct],0×0 ; on spécifie la subfonction 0 (charger un fichier)
mov eax,dword [dbid+32]
mov [fileinfo.bytes],eax ; on spécifie la taille à lire
mov [fileinfo.buffer],0×20000 ; on charge le fichier à cette adresse
mov [fileinfo.ptr_path],src ; l’adresse vers le nom du fichier a charger

mov eax,70
mov ebx,fileinfo
int 0×40

D) il ne reste plus qu’à écrire le nouveau fichier

mov [fileinfo.subfunct],0×2 ; on spécifie la subfonction 2 (ecrire un fichier)
mov [fileinfo.ptr_path],dst ; l’adresse vers le nom du fichier a ecrire

mov eax,70
mov ebx,fileinfo
int 0×40


Menuet Dynamic Library

août 15, 2006

J’ai peu-être trouvé la solution pour implémenter la dernière possibilité à propos des pilotes!!!

J’ai réussi à coder un programme qui au démarage charge un fichier binaire:

dans ce fichier il ya

l’adresse à laquelle le fichier doit être chargé
l’adresse des différentes fonctions.

cette démo démontre comment exécuter le code d’un fichier chargé dynamiquement , et je pense qu’il serai facile de faire pareil pour les pilotes qui seraient chargé par les programes qui en ont besoins.

le code de la librairie se présente finalement come suit:

org adresse_de_reference
dd adresse_ou_la_librairie_doit_etre charge
dd adresse_de_la_fonction1
dd adresse_de_la_fonction2
dd adresse_de_la_fonction3

fonction1:
code
ret

fonction2:
code
ret.

et ainsi de suite pour les autres fonctions.

le programme charge la librairie (macro mdl_load) ainsi:
il charge les 4 premiers octets (qui contienent l’adresse où elle doitêtre placée)
il enregistre la taille du fichier
il enregistre l’adresse de chargement
il charge la totalite du fichier au bon emplacement

pour lancer une fonction (macro mdl_call) :
on spécifie l’adresse de la variable contenant l’adresse (adresse de structure+12)
on specifie le numero de la fonction
il verifie que le numero est superieur à Zero

il calcule l’adresse de la fonction:
adresse_librairie_+(numero_fonction*4)
il fait un call vers l’adresse “call [adresse]“

MDL.ZIP

je vous donne les sources à analyser , le fichier zip contient:
test.asm (code du programme principal)
mdl.inc (code relatif au système de librairie dynamique)
mdl.asm (code de la librairie d’expérimentation)

test binaire du programme
mdl.mdl binaire de la librairie

nouvelle version avec utilisation de la fonction 70:
mdl3.zip

Dernière version, plus utile et plus aboutie. Dans cette version on passe les paramètres dans la pile et on fait le cal. La fonction dans le module lis les paramètres, effectures les opérations et renvoie la valeur de retour en la mettant dans la  pile (c’est comme ça que C le fait de toute manière).
Pour cette version, j’ai voulu créer une bibliothèque vraiment utile pour le programmeur alors j’ai choisi d’implémenter  les fonctions ipc de menuet de manière simplifiée. Les Fonctions implémentées sont:

  • dword IPC_get_proc_pid (char* proc_name);
  • dword IPC_send(dword pid, char* message, dword msglen);
  • void IPC_init();
  • ipc-msg* IPC_receive();
  • IPC_get_proc_pid va renvoier le pid du programme spécifié
  • IPC_send va envoyer au programme identifié par pid , le message qui a une longueur de msglen)
  • IPC_init va initialiser la zone de réception des messages (limité à un seul message, réinitialisé à chaque réception)
  • IPC_receive va renvoyer l’adresse de la structure contenant le message:
  • +0 dword msg.pid
  • +4 dword msg.len
  • +8 db  msg.data

ipc2.zip


Une suggestion pour des pilotes

août 15, 2006

Ce qui m’enuie beaucoup dans MenuetOS, c’est que ma carte son n’est pas supportée!! C’est pourtant une AC97. Et j’imagine que ce n’est pas la seule carte non supportée (en fait, seul les sound-blaster et comptabiles fonctionnent).

La solution à mon problème serait d’écrire un pilote pour celle-ci. Mais je ne sais pas vraiment comment je pourai l’implémenter dans menuet.

J’avais tout d’abord penssé à ajouter un .h dans les sources du noyaux, ajouter des syscalls et programmer des applications pour l’utiliser (ou bien passer par les syscalls de la sb16 et coder une fonction de détection).
C’est bien beau tout ça, mais si on devait implémenter tout les pilotes audio de cette manière, le noyau n’en finirai pas de grossir. Alors que j’ai pas besoin des autres pilotes.
Vous me direz:”Mouai t’as qu’à supprimer les pilotes dont t’as pas besoin”. d’accord, mais le comun des mortels, il ne sait pas comment faire ça, on va pas leur obliger de recompiler leur noyau hein.

Ya une autre solution, des modules qu’on charge si on en a besoin. Ouai, c pas mal comme idée, le hic, c’est qu’il faut implémenter un système de “modèles de pilotes” qui définirai tout, et pour finir, on dit adieux à une des principales qualitées de MenuetOS qui est la suppression d’un maximum d’interface (layer) qui finissent par provoquer des bugs dans le système.

Alors, j’ai un peu pioché sur le net (merci google), et j’ai trouvé deux solution viables.

La première est, comme dans les système à micro noyaux (qns, minix, gnu/hurd), que le pilote serai une sorte de serveur. Entendez par là que ce serai un programme comme un autre, à qui le client (lecteur audio par exemple) enverai des rêquetes, et de qui il reçevrai des réponses. Ce procédé est réalisable par ces manières:
1) La communication inter-processus (ipc)
2) la pile tcp-ip(socket)
3) Implémenter un système de fichier virtuels pour les périfériques (genre /dev)
4) écrire les entrées-sortires dans des fichiers sur le système de fichier

encore faudrait-il que le programme sache avec quel pilote communiquer (j’imagine qu’une sorte d’hal en mode utilisateur pourai être possible)

la deuxième solution (ma préférée), comme dans les exo-noyaux, est , me semble-t-il, la plus facile à réaliser. Elle consiste, à coder un pilote de cette manière:

; on comence par l’en-tête qui contien une table avec l’adresse d’entrée de chaque fonction

dd fonction1
dd fonction2
dd fonction3

;on écrit ensuite les fonctions
fonction1:
routines de la fonction
routines de la fonction
ret
… (idem pour les autres fonctions).

ensuite on le compile et on a notre pilote en mode utilisateur. En effet, MenuetOS permet au périfériques de réserver des irq, et ainsi de piloter des périfériques tels que la carte audio.

dans notre programme on chargera le pilote comme un fichier, à une adresse connue (dans l’espace du processus), par la fonction 58:

mov eax,58
mov ebx,drvinfo
int 0×40

drvinfo corespond à l’adresse des paramètres de la fonction, qui donne:

drvinfo:
.mode dd 8 ;en lecture lba(pour accéder au disque dûr si le pilote y est)
.block dd 0×0 ;nombre de block à lire (0 correspondant à l’entièreté du fichier)
.set dd 0×1 ;on doit toujours metre à 1 pour ce mode
.data dd 0×20000 ;ce qui nous intéresse particulièrement, l’adresse de chargement des données
.workarea dd 0×100000 ;espace nécessaire pour l’os
.path db ‘/hd/1/menuetos/drv/sound.drv’,0 ;chemin complet du fichier

une fois le fichier chargé, on peux allors accéder aux fonctions du pilotes, les adresses étant dans l’en-tête du fichier:
[addr_fonction1]=[drvinfo.data +0]
[addr_fonction2]=[drvinfo.data +4]
[addr_fonction3]=[drvinfo.data +8]

et pour appeler une fonction on fait simplement:

call [addr_fonction1] ;ce qui appelle la fonction1
ou
call [drvinfo.data+0] :ce qui appelle la fonction1 (pour la fonction2 on met +4,etc…)

Je pense que mon brainstorming a déjà pas mal commencé, mais je vais encore y réfléchir et vous donner des nouvelles de mon avancement.