cos2000v2/lib/shell.c

750 lines
19 KiB
C

/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
#include "vga.h"
#include "3d.h"
#include "matrix.h"
#include "video.h"
#include "interrupts.h"
#include "asm.h"
#include "cpu.h"
#include "string.h"
#include "gdt.h"
#include "shell.h"
#include "math.h"
#include "debug.h"
#include "VGA/ansi.c"
#include "3D/sphere.c"
#include "3D/man.c"
#include "memory.h"
#include "syscall.h"
#include "process.h"
static command commands[] = {
{"reboot", "", &rebootnow},
{"clear", "", &clear},
{"mode", "", &mode},
{"detectcpu", "", &detectcpu},
{"test2d", "", &test2d},
{"regs", "", &showregs},
{"gdt", "", &showgdt},
{"idt", "", &showidt},
{"info", "", &showinfo},
{"err", "", &err},
{"test", "", &test},
{"view", "", &view},
{"disasm", "", &disas},
{"bpset", "", &bpset},
{"bpclr", "", &bpclr},
{"help", "", &help},
{"logo", "", &logo},
{"font", "", &sfont},
{"test3d", "", &test3d},
{"detectpci", "", &detectpci},
{"mem", "", &showmem},
{"testmem", "", &testmem},
{"testtask", "", &testtask},
{"ps", "", &ps},
};
/*******************************************************************************/
/* Shell, traite les commandes */
void shell()
{
static u8 field[] =
" \000";
static u8 item[] = " \000";
int i;
bool found;
while (true)
{
print("\r\n# ");
getstring(&field);
print("\r\n");
if (strgetnbitems(&field, ' ') < 1)
continue;
strgetitem(&field, &item, ' ', 0);
strtolower(&item);
found = false;
for (i = 0; i < sizeof(commands) / sizeof(commands[0]);
i++)
{
if (strcmp(&item, &commands[i].name) == 0)
{
(*commands[i].function) (&field);
found = true;
break;
}
}
if (!found)
printf("Commande inconnue !\r\n\000");
}
}
int test(void)
{
print("Fonction de test !\r\n");
return;
}
/*******************************************************************************/
/* Afiche les processus */
static u8* processstatus[] = {"LIBRE","PRET ","EXEC.","PAUSE"};
static u8* taskstatus[] = {"PRET ","EXEC.","PAUSE"};
/*******************************************************************************/
/* Affiche les tâches et processus */
int ps()
{
print("*** Processus en memoire\r\n| PID | Parent|Status|K|P.|Directo.|Pages...\r\n");
process* aprocess=findprocess((pid_t)1);
while(true)
{
printf("|%Y|%Y| %s|%c|%hh u|%Y|",(u32)aprocess->pid,(u32)aprocess->parent,processstatus[aprocess->status],(aprocess->iskernel?'X':' '),aprocess->priority,(u32)aprocess->pdd);
if (aprocess->pdd!=NULL) virtual_pd_show(aprocess->pdd);
print("\r\n");
aprocess=getnextprocess(aprocess,PROCESS_STATUS_ALL);
if (aprocess==NULL || aprocess->pid==(pid_t)1) break;
}
print("\r\n\r\n*** Taches en memoire\r\n| TID | PID |Status| CS | EIP | SS | ESP |\r\n");
aprocess=findprocess((pid_t)1);
task* atask;
while(true)
{
atask=findfirsttask(aprocess);
while(true)
{
printf("|%Y|%Y| %s|%hY|%Y|%hY|%Y|\r\n",(u32)atask->tid.number,(u32)atask->tid.pid,taskstatus[atask->status],atask->dump.cs,atask->dump.eip,atask->dump.ss,atask->dump.esp);
atask=getnexttask(atask,TASK_STATUS_ALL);
if (atask==NULL || (atask->tid.number==1 && atask->tid.pid==1)) break;
}
aprocess=getnextprocess(aprocess,PROCESS_STATUS_ALL);
if (aprocess==NULL || aprocess->pid==(pid_t)1) break;
}
}
/*******************************************************************************/
/* Test l'usage de création de tâche */
#include "TEST/test.c"
#include "TEST/test2.c"
int testtask()
{
print("*** Creation d'une tache\r\n");
pid_t pid;
pid = createprocess(&programs_test2, false);
runprocess(pid);
pid = createprocess(&programs_test, false);
runprocess(pid);
}
/*******************************************************************************/
/* Test la memoire */
int testmem()
{
u8 *test;
print("**** AVANT ALLOCATION\r\n");
showmem();
test = vmalloc(150 * 1024 * 1024); /* 10 pages */
print("**** APRES ALLOCATION\r\n");
showmem();
vfree(test);
print("**** APRES LIBERATION\r\n");
showmem();
}
/*******************************************************************************/
/* Affiche des informations sur la mémoire */
int showmem()
{
u32 libre = getmemoryfree();
u32 total = physical_getmemorysize();
printf("Memoire physique (TOTAL)\r\n -libre \33[40D\33[15C%H (%.2f%%)\r\n -occupee \33[40D\33[15C%H\r\n -total \33[40D\33[15C%H\r\n\r\n", libre, ((float) libre / total * 100.0f), total - libre, total);
printf("Memoire HEAP (NOYAU) - % u blocs\r\n -libre \33[40D\33[15C%H\r\n -occupee \33[40D\33[15C%H\r\n -allouables \33[40D\33[15C%H\r\n\r\n", getmallocnb(), getmallocfree(), getmallocused(), getmallocnonallocated());
printf("Plan de memoire (NOYAU)\r\n -IDT \33[40D\33[15C%X\r\n -GDT \33[40D\33[15C%X\r\n -PGD \33[40D\33[15C%X\r\n -STACK \33[40D\33[15C%X\r\n -CODE \33[40D\33[15C%X\r\n -PAGES \33[40D\33[15C%X\r\n -HEAP \33[40D\33[15C%X\r\n -VESAFB \33[40D\33[15C%X\r\n\r\n", IDT_ADDR, GDT_ADDR, KERNEL_PD_ADDR, KERNEL_STACK_ADDR, KERNEL_CODE_ADDR, KERNEL_PAGES, KERNEL_HEAP, VESA_FBMEM);
printf("Memoire Virtuelle (NOYAU)\r\n -pages libres \33[40D\33[16C% u\r\n -pages occupees \33[40D\33[16C% u\r\n", virtual_getpagesfree(), virtual_getpagesused());
return;
}
/*******************************************************************************/
/* Affiche les périphériques PCI */
int detectpci()
{
scanPCI();
}
/*******************************************************************************/
/* Change la police courante */
int sfont(u8 * commandline)
{
if (strgetnbitems(commandline, ' ') < 2)
{
print("Syntaxe de la commande FONT\r\nfont \33[32mpolice\r\n\r\n \33[32mpolice\33[0m\33[0m\33[25D\33[10C - \33[Nom de la police de caractere\r\n");
return;
}
setfont(strgetpointeritem(commandline, ' ', 1));
}
/*******************************************************************************/
/* Affiche le logo */
int logo()
{
print(ansilogo);
return;
}
/*******************************************************************************/
/* Renvoie les commandes disponibles */
int help()
{
print("Commandes disponibles :\r\n\r\n");
for (u32 i = 0; i < sizeof(commands) / sizeof(commands[0]); i++)
{
printf("%s \r\n", &commands[i].name);
}
return 0;
}
/*******************************************************************************/
/* Met un breakpoint */
int bpset(u8 * commandline)
{
u8 arg[] = " \000";
u8 *numero;
u8 *pointer;
u8 type = DBG_EXEC;
if (strgetnbitems(commandline, ' ') < 3)
{
print("Syntaxe de la commande BPSET\r\nbpset \33[32mnumero address [type]\r\n\r\n \33[32mnumero\33[0m\33[0m\33[25D\33[10C - numero du breakpoint (0-3)\r\n \33[32madresse\33[0m\33[25D\33[10C - adresse du breakpoint\r\n \33[32mtype\33[0m\33[25D\33[10C - type de breakpoint (0-3)\r\n");
return;
}
strgetitem(commandline, &arg, ' ', 1);
numero = strtoint(&arg);
if (numero > 3)
{
print("numero incorrect");
return;
}
strgetitem(commandline, &arg, ' ', 2);
pointer = strtoint(&arg);
if (strgetnbitems(commandline, ' ') == 4)
{
strgetitem(commandline, &arg, ' ', 3);
type = strtoint(&arg);
}
if (type > DBG_READWRITE)
{
print("type incorrect");
return;
}
setdebugreg(numero, pointer, type);
}
/*******************************************************************************/
/* Retire un breakpoint */
int bpclr(u8 * commandline)
{
u8 arg[] = " \000";
u8 *numero;
if (strgetnbitems(commandline, ' ') < 2)
{
print("Syntaxe de la commande BPCLR\r\nbpclr \33[32mnumero\r\n\r\n \33[32mnumero\33[0m\33[0m\33[25D\33[10C - numero du breakpoint (0-3)\r\n");
return;
}
strgetitem(commandline, &arg, ' ', 1);
numero = strtoint(&arg);
if (numero > 3)
{
print("numero incorrect");
return;
}
setdebugreg(numero, 0x0, DBG_CLEAR);
}
/*******************************************************************************/
/* Desassemble une zone de mémoire donnée */
int disas(u8 * commandline)
{
u8 arg[] = " \000";
u8 *size;
u8 *pointer;
if (strgetnbitems(commandline, ' ') < 3)
{
print("Syntaxe de la commande DISASM\r\ndisasm \33[32madresse taille\r\n\r\n \33[32madresse\33[0m\33[0m\33[25D\33[10C - Adresse a visualiser\r\n \33[32mtaille\33[0m\33[25D\33[10C - nombre d'octets a desassembler <256\r\n");
return;
}
strgetitem(commandline, &arg, ' ', 1);
pointer = strtoint(&arg);
size = pointer;
strgetitem(commandline, &arg, ' ', 2);
size += strtoint(&arg);
while (pointer < size)
{
pointer += disasm(pointer, NULL, true);
}
}
/*******************************************************************************/
/* Génère des exceptions */
int view(u8 * commandline)
{
u8 arg[] = " \000";
u32 address;
u8 size;
u8 *pointerb;
u16 *pointerw;
u32 *pointerd;
u8 format;
u8 nbligne;
if (strgetnbitems(commandline, ' ') < 3)
{
print("Syntaxe de la commande VIEW\r\nview \33[32madresse taille [size] [nbligne]\r\n\r\n \33[32madresse\33[0m\33[0m\33[25D\33[10C - Adresse a visualiser\r\n \33[32mtaille\33[0m\33[25D\33[10C - nombre d'octets a visualiser <256\r\n \33[32mformat\33[0m\33[25D\33[10C - c (ascii) b (octet) w (mot) d (double mot)\r\n \33[32mnbligne\33[0m\33[25D\33[10C - nombre d'octets a visualiser par ligne\r\n");
return;
}
strgetitem(commandline, &arg, ' ', 1);
address = strtoint(&arg);
strgetitem(commandline, &arg, ' ', 2);
size = strtoint(&arg);
if (strgetnbitems(commandline, ' ') < 4)
format = 'b';
else
{
strgetitem(commandline, &arg, ' ', 3);
format = arg[0];
}
switch (format)
{
case 'c':
pointerb = address;
nbligne = 12;
break;
case 'b':
pointerb = address;
nbligne = 22;
break;
case 'w':
pointerw = address;
nbligne = 13;
break;
case 'd':
pointerd = address;
nbligne = 7;
break;
}
if (strgetnbitems(commandline, ' ') == 5)
{
strgetitem(commandline, &arg, ' ', 4);
nbligne = strtoint(&arg);
}
printf("Adresse %Y - % hhu", address, size);
for (u32 i = 0; i < size; i++)
switch (format)
{
case 'c':
if (i % nbligne == 0)
printf("\r\n:%Y - ", pointerb);
printf("%hhY \33[40C%c\33[41D",
*(pointerb), *(pointerb++));
break;
case 'b':
if (i % nbligne == 0)
printf("\r\n:%Y - ", pointerb);
printf("%hhY ", *(pointerb++));
break;
case 'w':
if (i % nbligne == 0)
printf("\r\n:%Y - ", pointerw);
printf("%hY ", *(pointerw++));
break;
case 'd':
if (i % nbligne == 0)
printf("\r\n:%Y - ", pointerd);
printf("%Y ", *(pointerd++));
break;
}
}
/*******************************************************************************/
/* Génère des exceptions */
int err(u8 * commandline)
{
u8 arg[] = " \000";
u32 argint;
if (strgetnbitems(commandline, ' ') < 2)
{
print("Syntaxe de la commande ERR\r\nerr \33[32mexception\r\n\r\n exception\33[0m\33[25D\33[10C - code de l'exception\r\n");
return;
}
strgetitem(commandline, &arg, ' ', 1);
argint = strtoint(&arg);
switch (argint)
{
case 0:
print("Creation d'une erreur de division par 0 !\r\n");
asm("movl $0x0,%ecx; divl %ecx");
break;
case 1:
print("Creation d'un breakpoint !\r\n");
setdebugreg(0, &test, DBG_EXEC);
test();
break;
case 2:
print("NON GERE!\r\n");
break;
case 3:
print("Creation d'une erreur interruption 3 !\r\n");
asm("int $0x3");
break;
case 4:
print("NON GERE!\r\n");
break;
case 5:
print("NON GERE!\r\n");
break;
case 6:
print("Creation d'une erreur d'opcode invalide !\r\n");
asm("mov %cr7, %eax");
break;
case 7:
print("NON GERE!\r\n");
break;
case 8:
print("NON GERE!\r\n");
break;
case 9:
print("NON GERE!\r\n");
break;
case 10:
print("NON GERE!\r\n");
break;
case 11:
print("Creation d'une erreur segment non present !\r\n");
setidt(&err, SEL_KERNEL_CODE, INTGATE, 104);
asm("int $0x68");
break;
case 12:
print("NON GERE!\r\n");
break;
case 13:
print("Creation d'une erreur general fault !\r\n");
asm("mov $0x666, %ax; ltr %ax");
break;
case 14:
if (random(0, 100) > 50)
{
print("Creation d'une erreur de page en ecriture !\r\n");
asm("movl $0x66666666,(0xE0000000)");
}
else
{
print("Creation d'une erreur de page en lecture !\r\n");
asm("movl (0xD0000000),%eax");
}
break;
case 15:
print("NON GERE!\r\n");
break;
case 16:
print("NON GERE!\r\n");
break;
case 17:
print("NON GERE!\r\n");
break;
case 18:
print("NON GERE!\r\n");
break;
default:
print("Exception qui n'existe pas !!!\r\n");
break;
}
return 0;
}
/*******************************************************************************/
/* Information sur le démarrage */
int showinfo()
{
return 0;
}
/*******************************************************************************/
/* Affiche les registres */
int showregs()
{
int20;
return 0;
}
/*******************************************************************************/
/* Change le mode */
int mode(u8 * commandline)
{
u8 arg[] = " \000";
u32 argint;
if (strgetnbitems(commandline, ' ') < 2)
{
print("Syntaxe de la commande MODE\r\nmode \33[32mmodevideo\r\n\r\n modevideo\33[0m\33[25D\33[10C - mode video a initialiser (>0x80 = graphique)\r\n");
return;
}
strgetitem(commandline, &arg, ' ', 1);
argint = strtoint(&arg);
changemode(argint);
return 0;
}
/*******************************************************************************/
/* Efface l'écran */
int clear()
{
clearscreen();
return 0;
}
/*******************************************************************************/
/* Redemarre */
int rebootnow()
{
print("<Appuyer sur une touche pour redemarrer>");
waitascii();
reboot();
return 0;
}
/*******************************************************************************/
/* Teste les fonctionnalités 3D */
int test3d()
{
videoinfos *vinfo = getvideo_info();
if (!vinfo->isgraphic)
{
print("Mode graphique necessaire afin de lancer ce programme\r\n");
return 1;
}
model3d model;
float factor = 100.0f;
type3D type = TYPE3D_POINTS;
matrix44 rotatex, rotatey, rotatez, mrotatex, mrotatey, mrotatez,
identity;
matrix44_homogen(&identity);
matrix44_rotation_x(0.1f, &rotatex);
matrix44_rotation_y(0.1f, &rotatey);
matrix44_rotation_z(0.1f, &rotatez);
matrix44_rotation_x(-0.1f, &mrotatex);
matrix44_rotation_y(-0.1f, &mrotatey);
matrix44_rotation_z(-0.1f, &mrotatez);
matrix44 *transformation = &identity;
vector4 origin = { 0.0f, 0.0f, 0.0f, 0.0f };
vector4 cubeorigin = { 0.0f, 0.0f, 0.0f, 0.0f };
origin.x = vinfo->currentwidth / 2.0f;
origin.y = vinfo->currentheight / 2.0f;
origin.z = 70.0f;
cube(&model, &cubeorigin, 35.0f);
u8 achar = ' ';
u8 i;
while (achar != 'q' && achar != 'Q')
{
clearscreen();
show3dmodel(&model, transformation, &origin, factor, type);
achar = waitascii();
switch (achar)
{
case '1':
load3ds(&man, sizeof(man), &model);
break;
case '2':
load3ds(&sphere, sizeof(sphere), &model);
break;
case 17:
transformation = &rotatex;
break;
case 18:
transformation = &mrotatex;
break;
case 19:
transformation = &rotatey;
break;
case 20:
transformation = &mrotatey;
break;
case 2:
transformation = &rotatez;
break;
case 3:
transformation = &mrotatez;
break;
case '-':
factor -= 10.0;
break;
case '+':
factor += 10.0;
break;
case '*':
switch (type)
{
case TYPE3D_POINTS:
type = TYPE3D_LINES;
break;
case TYPE3D_LINES:
type = TYPE3D_POINTS;
break;
}
break;
}
}
return 0;
}
/*******************************************************************************/
/* Teste les fonctionnalités 2D graphiques */
int test2d()
{
videoinfos *vinfo = getvideo_info();
if (!vinfo->isgraphic)
{
print("Mode graphique necessaire afin de lancer ce programme\r\n");
return 1;
}
struct vertex2d a, b, c;
randomize();
u32 color;
for (int i = 0; i < 2000; i++)
{
a.x = random(0, vinfo->currentwidth);
a.y = random(0, vinfo->currentheight);
b.x = random(0, vinfo->currentwidth);
b.y = random(0, vinfo->currentheight);
if (vinfo->currentdepth > 24)
color = egatorgb(random(0, 16));
else if (vinfo->currentdepth == 8)
color = random(0, 63);
else
color = random(0, 16);
v_line(&a, &b, color);
}
waitascii();
for (int i = 0; i < 2000; i++)
{
a.x = random(0, vinfo->currentwidth);
a.y = random(0, vinfo->currentheight);
b.x = random(0, vinfo->currentwidth);
b.y = random(0, vinfo->currentheight);
c.x = random(0, vinfo->currentwidth);
c.y = random(0, vinfo->currentheight);
if (vinfo->currentdepth > 24)
color = egatorgb(random(0, 16));
else if (vinfo->currentdepth == 8)
color = random(0, 63);
else
color = random(0, 16);
trianglefilled(&a, &b, &c, color);
triangle(&a, &b, &c, egatorgb(4));
}
return 0;
}
/*******************************************************************************/
/* Lit l'IDT et l'affiche */
int showidt()
{
u32 index, i = 0;
idtdes *desc;
struct idtr idtreg;
sidt(idtreg);
printf("Information sur l'IDT\r\nAdresse:%X Limite:%hX\r\n",
idtreg.base, (u32) idtreg.limite);
desc = idtreg.base;
for (index = 0; index < idtreg.limite / sizeof(idtdes); index++)
{
u32 select = desc[index].select;
u32 offset =
desc[index].offset0_15 +
(desc[index].offset16_31 << 16);
u32 type = desc[index].type & 0x0F00;
u8 *typestr1, *typestr2;
if (i >= 32 & i <= 39)
typestr1 = "IRQ master";
else if (i >= 96 & i <= 103)
typestr1 = "IRQ slave ";
else if (i < 19)
typestr1 = "EXCEPTION ";
else
typestr1 = "INTERRUPT ";
if (type == INTGATE)
typestr2 = "INTGATE";
else if (type == TRAPGATE)
typestr2 = "TRAPGATE";
else if (type == TASKGATE)
typestr2 = "TASKGATE";
else if (type == CALLGATE)
typestr2 = "CALLGATE";
else if (type == LDTDES)
typestr2 = "LDTDES";
else
print("inconnu");
printf("%s % hu %hY:%Y - %s\r\n", typestr1, i++, select,
offset, typestr2);
if (i % 32 == 0)
{
print("\r\n<Appuyez sur une touche>\r\n");
waitascii();
}
}
return 0;
}
/*******************************************************************************/
/* Lit les descripteurs GDT et les affiche */
int showgdt()
{
u32 index;
struct gdtr gdtreg;
sgdt(gdtreg);
printf("Information sur la GDT\r\nAdresse:%X Limite:%hX\r\n",
gdtreg.base, gdtreg.limite);
for (index = 0; index < gdtreg.limite; index += sizeof(gdtdes))
{
if (!isdesvalid(index))
printf("\033[31m");
printf("SEL =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\033[0m\r\n", index, getdesbase(index), getdeslimit(index), getdesdpl(index), getdestype(index), getdessize(index), getdesbit3(index), getdesbit2(index), getdesbit1(index), getdesalign(index));
}
return 0;
}
/*******************************************************************************/
/* Detecte et affiche les information sur le CPU */
int detectcpu()
{
cpuinfo cpu;
u8 noproc[] = "\033[31mInconnu\033[0m\000";
strcpy(&noproc, &cpu.detectedname);
getcpuinfos(&cpu);
printf("\r\nDetection du processeur\r\033[1m Revision \t:%d\r Modele \t:%d\r Famille \t:%d\r Nom cpuid\t:%s\rJeux d'instruction\t:%s\033[0m\r\n\000", cpu.stepping, cpu.models, cpu.family, &cpu.detectedname, &cpu.techs);
return 0;
}
/*******************************************************************************/