Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

shell.c

Go to the documentation of this file.
00001 /*!     \file shell/shell.c
00002  *      \brief MiniShell - a very very simple shell.
00003  *      \author Andrea Righi <drizzt@inwind.it>
00004  *      \date Last update: 2003-11-15
00005  *      \note Copyright (C) 2003 Andrea Righi
00006  */
00007 
00008 #include <const.h>
00009 #include <errno.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 
00014 #include <arch/i386.h>
00015 #include <arch/mem.h>
00016 #include <arch/paging.h>
00017 #include <arch/v86.h>
00018 
00019 #include <kernel/clock.h>
00020 #include <kernel/console.h>
00021 #include <kernel/elf32.h>
00022 #include <kernel/ext2.h>
00023 #include <kernel/fat.h>
00024 #include <kernel/floppy.h>
00025 #include <kernel/Ide.h>
00026 #include <kernel/IdeDebug.h>
00027 #include <kernel/IdeTimer.h> // must remove
00028 #include <kernel/IdeLow.h>   // must remove
00029 #include <kernel/kernel.h>
00030 #include <kernel/keyboard.h>
00031 #include <kernel/kmalloc.h>
00032 #include <kernel/pci.h>
00033 #include <kernel/speaker.h>
00034 #include <kernel/task.h>
00035 #include <kernel/serial.h>
00036 #include <kernel/time.h>
00037 
00038 #include <net/arp.h>
00039 #include <net/eth.h>
00040 #include <net/icmp.h>
00041 
00042 #include <kernel/shell.h>
00043 
00044 /** \ingroup UserInterface
00045  *  \defgroup UIMiniShell MiniShell
00046  *  A simple text-based shell.
00047  *  @{
00048  */
00049 
00050 #define SH_HELP                 0
00051 #define SH_UNAME                1
00052 #define SH_CLEAR                2
00053 #define SH_REBOOT               3
00054 #define SH_DUMP                 4
00055 #define SH_READ                 5
00056 #define SH_WRITE                6
00057 #define SH_PAGES                7
00058 #define SH_MEM                  8
00059 #define SH_CHECKMEM             9
00060 #define SH_FRAMES               10
00061 #define SH_BG                   11
00062 #define SH_V86EXEC              12
00063 #define SH_V86BG                13
00064 #define SH_TEST                 14
00065 #define SH_CPUID                15
00066 #define SH_MOUNT                16
00067 #define SH_LS                   17
00068 #define SH_CAT                  18
00069 #define SH_CD                   19
00070 #define SH_PS                   20
00071 #define SH_KILL                 21
00072 #define SH_RS232                22
00073 #define SH_EXEC                 23
00074 #define SH_PCISCAN              24
00075 #define SH_ETH_ARP              25
00076 #define SH_RTL8139_INIT         26
00077 #define SH_ETH_PING             27
00078 #define SH_HALT                 28
00079 #define SH_RM                   29
00080 #define SH_ELF                  30
00081 // **************** Luca Giovacchini (Ide) ****************
00082 #define SH_IDETEST              31
00083 #define SH_IDEREAD              32
00084 #define SH_IDEWRITE             33
00085 #define SH_IDEDEVICEINFO        34
00086 // ********************************************************
00087 // ****************** Filippo Brogi ***********************
00088 #define SH_LS_EXT2              35
00089 #define SH_CAT_EXT2             36
00090 #define SH_CD_EXT2              37
00091 // ********************************************************
00092 #define SH_TIME                 38
00093 
00094 //! The commands supported in MiniShell.
00095 static CMD_t commands[] = {
00096 { SH_ETH_ARP, "arp", "arp destination", "Send an ARP echo request to ip destination"},
00097 { SH_BG, "bg", "bg filename", "Execute a program in background"},
00098 { SH_V86BG, "bg-v86", "bg-v86 filename", "Execute a virtual 8086 mode program in background"},
00099 { SH_CAT, "cat", "cat filename", "Concatenate FILE to standard output"},
00100 // ******************** Filippo Brogi *********************
00101 { SH_CAT_EXT2, "cat2", "cat2 filename", "Concatenate ext2 FILE to standard output"},
00102 // ********************************************************
00103 { SH_CD, "cd", "cd [dir]", "Change the current directory"},
00104 // ******************** Filippo Brogi *********************
00105 { SH_CD_EXT2, "cd2", "cd2 [dir]", "Change the current ext2 directory"},
00106 // ********************************************************
00107 { SH_RS232, "chat", "chat <2400|4800|9600|19200|38400|56700|115200>", "Connect to /dev/modem on COM1"},
00108 { SH_CHECKMEM, "checkmem", "checkmem", "Create a background task to check frames stack integrity"},
00109 { SH_CLEAR, "clear", "clear", "Clear the screen"},
00110 { SH_CPUID, "cpuid", "cpuid", "Show informations about the CPU - Only for IA-32 INTEL(R)"},
00111 { SH_DUMP, "dump", "dump", "Register dump"},
00112 { SH_ELF, "elf", "elf filename", "Check if filename is a valid ELF32 file"},
00113 { SH_FRAMES, "frames", "frames", "Dump free frames"},
00114 { SH_EXEC, "fg", "fg filename", "Execute a program in foreground (you can use ./ instead of fg)"},
00115 { SH_V86EXEC, "fg-v86", "fg-v86 filename", "Execute a virtual 8086 mode program in foreground"},
00116 { SH_HALT, "halt", "halt", "Power down the system (if possible, otherwise halt)"},
00117 { SH_HELP, "help", "help [cmd]", "Show the command help"},
00118 // **************** Luca Giovacchini (Ide) ****************
00119 { SH_IDEDEVICEINFO, "idedeviceinfo","idedeviceinfo","Display complete info of a specified device"},
00120 { SH_IDEREAD, "ideread", "ideread", "Read a block from a device on a specified ide channel"},
00121 { SH_IDETEST, "idetest", "idetest", "test ide routine for debuging purpose"},
00122 { SH_IDEWRITE, "idewrite", "idewrite", "Write a block to a device on specified ide channel"},
00123 // ********************************************************
00124 { SH_RTL8139_INIT, "ifconfig", "ifconfig <up|down> [promisc]", "Initialize RTL8139 ethernet card"},
00125 { SH_KILL, "kill", "kill [pid]", "Kill a task"},
00126 { SH_LS, "ls", "ls", "List informations about FILEs"},
00127 // ******************** Filippo Brogi *********************
00128 { SH_LS_EXT2, "ls2", "ls2", "List information about ext2 FILEs"},
00129 // ********************************************************
00130 { SH_MEM, "mem", "mem", "Dump kernel memory map"},
00131 { SH_MOUNT, "mount", "mount", "Mount the FAT12 filesystem on the floppy"},
00132 { SH_ETH_PING, "ping", "ping destination", "PING to the ip destination"},
00133 { SH_PAGES, "pages", "pages", "Dump dirty pages"},
00134 { SH_PCISCAN, "pciscan", "pciscan", "Scan for PCI devices"},
00135 { SH_PS, "ps", "ps", "Print the state of every processes"},
00136 { SH_READ, "read", "read [block]", "Read a block from the floppy to the buffer"},
00137 { SH_REBOOT, "reboot", "reboot", "Reboot the system"},
00138 { SH_RM, "rm", "rm filename", "Remove a file"},
00139 { SH_TEST, "test", "test [num]", "Create <num> auto-killing tasks"},
00140 { SH_TIME, "time", "time", "Print the UNIX timestamp (seconds since 1970-01-01 00:00:00)"},
00141 { SH_UNAME, "uname", "uname", "Print kernel informations"},
00142 { SH_WRITE, "write", "write [block]", "Write a block from the buffer to the floppy"},
00143 
00144 };
00145 
00146 /** @} */ // end of UIMiniShell
00147 
00148 // **************** Luca Giovacchini (Ide) ****************
00149 void Sh_IdeTest()
00150 {
00151         kprintf("\n\rThis command is only for debug purpose.\n\r");
00152 }
00153 
00154 void Sh_IdeRead()
00155 {
00156         int Dev;
00157         int Lba;
00158         int Err=FALSE;
00159         byte DataBuffer[512];
00160 
00161         kprintf("\n\rInsert the channel number (0 or 1): 0\b");
00162         scanf("%i", &Dev);
00163         kprintf("\n\rChannel %i Selected",Dev);
00164         if ( Dev==0 )
00165                 SelectAtaChannel(CC_PRIMARY);
00166         else if ( Dev==1 )
00167                 SelectAtaChannel(CC_SECONDARY);
00168         else
00169         {
00170                 kprintf("\n\rBad Channel Number: Channel 0 will be selected");
00171                 SelectAtaChannel(CC_PRIMARY);
00172         }
00173 
00174         kprintf("\n\rInsert the device number to Read (0 or 1): 0\b");
00175         scanf("%i", &Dev);
00176         kprintf("\n\rDevice %i Selected",Dev);
00177         if ( Dev==0 || Dev==1 )
00178         {
00179 
00180                 kprintf("\n\rInsert Lba : ");
00181                 scanf("%i", &Lba);
00182                 kprintf("\n\rLba Selected %i",Lba);
00183 
00184                 Err=ReadSectorsLba(Dev,(int64) Lba,1,(word *) &DataBuffer,TRUE);
00185                 if (Err)
00186                         ShowIdeErrorMessage(Err,TRUE);
00187                 else
00188                 {
00189                         kprintf("\n\r HEX DATA");
00190                         ShowMatrixData(DataBuffer,1,16,20,512,DBG_SHOWMAT_HEX);
00191                         WaitKeyPress(MSG_PRESSKEY);
00192                         kprintf("\n\r CHAR DATA");
00193                         ShowMatrixData(DataBuffer,1,40,20,512,DBG_SHOWMAT_ASCII);
00194                         WaitKeyPress(MSG_PRESSKEY);
00195                 }
00196         }
00197         else
00198                 kprintf("\n\rBad Device Number");
00199         kprintf("\n\r ");
00200 }
00201 
00202 void Sh_IdeWrite()
00203 {
00204         int Dev;
00205         int i=0;
00206         int Lba;
00207         char DataBuffer[512];
00208         int Pattern;
00209         int Err=FALSE;
00210         byte Data;
00211 
00212         kprintf("\n\rInsert the channel number (0 or 1): 0\b");
00213         scanf("%i", &Dev);
00214         kprintf("\n\rChannel %i Selected",Dev);
00215         if ( Dev==0 )
00216         {
00217                 SelectAtaChannel(CC_PRIMARY);
00218         }
00219         else if ( Dev==1 )
00220         {
00221                 SelectAtaChannel(CC_SECONDARY);
00222         }
00223         else
00224         {
00225                 kprintf("\n\rBad Channel Number Channel 0 will be selected");
00226                 SelectAtaChannel(CC_PRIMARY);
00227         }
00228 
00229 
00230         kprintf("\n\rInsert the device number to Write (0 or 1): 0\b");
00231         scanf("%i", &Dev);
00232         kprintf("\n\rDevice %i Selected",Dev);
00233         if ( Dev==0 || Dev==1 )
00234         {
00235 
00236                 kprintf("\n\rInsert Lba : ");
00237                 scanf("%i", &Lba);
00238                 kprintf("\n\rLba Selected %i",Lba);
00239 
00240                 kprintf("\n\rSpecify Type of Pattern To Write (1 byte in decimal format): ");
00241                 scanf("%i",&Pattern);
00242                 kprintf("\n\rPattern: %i",Pattern);
00243                 Data=(byte) Pattern;
00244                 for (i=0;i<512;i++)
00245                         DataBuffer[i]=Data;
00246 
00247                 Err=WriteSectorsLba(Dev,(int64) Lba,1,(word *) &DataBuffer,TRUE);
00248                 if (Err)
00249                         ShowIdeErrorMessage(Err,TRUE);
00250         }
00251         else
00252                 kprintf("\n\rBad Device Number");
00253         kprintf("\n\r ");
00254 
00255 }
00256 
00257 void Sh_IdeDeviceInfo()
00258 {
00259         int Dev;
00260 
00261         kprintf("\n\rInsert the channel number (0 or 1): 0\b");
00262         scanf("%i", &Dev);
00263         kprintf("\n\rChannel %i Selected",Dev);
00264         if ( Dev==0 )
00265                 SelectAtaChannel(CC_PRIMARY);
00266         else if ( Dev==1 )
00267                 SelectAtaChannel(CC_SECONDARY);
00268         else
00269         {
00270                 kprintf("\n\rBad Channel Number Channel 0 will be selected");
00271                 SelectAtaChannel(CC_PRIMARY);
00272         }
00273 
00274 
00275         kprintf("\n\rInsert the device number (0 or 1): 0\b");
00276         scanf("%i", &Dev);
00277         kprintf("\n\rDevice %i Selected",Dev);
00278         if ( Dev==0 || Dev==1 )
00279         {
00280                 ShowDeviceData(Dev,30);
00281         }
00282 }
00283 // ********************************************************
00284 
00285 // ******************** Filippo Brogi *********************
00286 
00287 void sh_cd2(char *argv)
00288 {
00289 // Change the current ext2 directory //
00290         if (argv[0]=='\0') return;
00291 
00292         cd_ext2(argv);
00293 }
00294 
00295 void sh_cat2(char *argv)
00296 {
00297 // Concatenate ext2 file to standard output //
00298         if (argv[0]=='\0')
00299         {
00300                 kprintf("\n\rcat2 requires argument\n\r");
00301                 return;
00302         }
00303         cat_ext2(argv);
00304 }
00305 // ********************************************************
00306 
00307 // Floppy buffer //
00308 byte fd_buffer[FDC_SECTOR_SIZE];
00309 
00310 void sh_read(char *argv)
00311 {
00312 // Read 1 sector from the floppy disk to the FDC buffer //
00313         int block, i;
00314 
00315         block = atoi(argv);
00316         kprintf("\n\rReading block %u...\n\r", block);
00317         kprintf("\n\r");
00318 
00319         memset(fd_buffer, 0, FDC_SECTOR_SIZE);
00320 
00321         for(i=0; i<3; i++)
00322                 if (fdc_read(block, fd_buffer, 1)) break;
00323 
00324         if (i != 3)
00325         for(i=0; i<512; i++)
00326                 kputchar(fd_buffer[i]);
00327         else
00328                 kprintf("\n\rFloppy I/O error. Unable to read the block!!!\n\r");
00329 
00330         kprintf("\n\r");
00331 }
00332 
00333 void sh_write(char *argv)
00334 {
00335 // Write 1 sector from the FDC buffer to the floppy disk //
00336         int block, i;
00337 
00338         block = atoi(argv);
00339         kprintf("\n\rWriting block %u...\n\r", block);
00340         for(i=0; i<3; i++)
00341                 if (fdc_write(block, fd_buffer, 1)) break;
00342 
00343         if (i == 3)
00344                 kprintf("\n\rFloppy I/O error. Unable to write the block!!!\n\r");
00345 }
00346 
00347 void sh_kill(char *argv)
00348 {
00349         kprintf("\n\rKilling task %i...", atoi(argv));
00350         if ( kill(atoi(argv)) )
00351                 kprintf(" OK!\n\r");
00352         else
00353                 kprintf("\n\rCannot kill this task!\n\r");
00354 }
00355 
00356 // --- Virtual 8086 mode ---------------------------------------------- //
00357 #define V86_START_ADDRESS       0x10000
00358 // Create a v86 foreground task.
00359 void sh_v86_exec(char *argv)
00360 {
00361         byte *file_buffer;
00362         int file_size;
00363         task_t *child;
00364         int status;
00365 
00366         if( !argv )
00367         {
00368                 kprintf("file name?\n");
00369                 return;
00370         }
00371         strtoupper(argv);
00372 
00373         // Get the file size if exists //
00374         file_size = get_file_size(argv);
00375 
00376         if (file_size != -1)
00377         {
00378                 // Create the task //
00379                 file_buffer = kmalloc(file_size);
00380                 load_file(argv, file_buffer);
00381                 child = create_v86_process((void *)V86_START_ADDRESS, file_buffer, file_size, argv);
00382                 kfree(file_buffer);
00383                 // Wait until the child is killed //
00384                 waitpid(child->pid, &status, 0);
00385         }
00386 }
00387 
00388 void sh_v86_bg(char *argv)
00389 {
00390 // Create a v86 background task                                         //
00391         byte *file_buffer;
00392         int file_size;
00393 
00394         if( !argv )
00395         {
00396                 kprintf("file name?\n");
00397                 return;
00398         }
00399         strtoupper(argv);
00400 
00401         // Get the file size if exists //
00402         file_size = get_file_size(argv);
00403 
00404         if (file_size != -1)
00405         {
00406                 // Create the task //
00407                 file_buffer = kmalloc(file_size);
00408                 load_file(argv, file_buffer);
00409                 create_v86_process((void *)V86_START_ADDRESS, file_buffer, file_size, argv);
00410                 kfree(file_buffer);
00411         }
00412 }
00413 // --- End of Virtual 8086 mode --------------------------------------- //
00414 
00415 //! \brief Parse parameters passed to the task by the command line.
00416 int sh_parse_params(const char *cmd_str, char ***argv, int *argc)
00417 {
00418         char *strtmp=NULL, *cmd_line=NULL;
00419         int i, len;
00420 
00421         // Initialize argv and argc                                     //
00422         *argv = (char **)NULL;
00423         *argc = 0;
00424 
00425         // Empty command line?!                                         //
00426         if ( cmd_str==NULL )
00427                 return( 0 );
00428         if ( *cmd_str == '\0' )
00429                 return( 0 );
00430 
00431         // Copy the command string into a temporary array               //
00432         if ( (len=strlen(cmd_str))!=0  )
00433                 cmd_line = kmalloc(len+1);
00434 
00435         if ( cmd_line == NULL )
00436                 return( -ENOMEM );
00437 
00438         strcpy( cmd_line, cmd_str );
00439 
00440         // Skip the initial spaces                                      //
00441         while( *cmd_line == ' ' )
00442                 cmd_line++;
00443 
00444         // Calculate the number of parameters (argc)                    //
00445         strtmp = cmd_line;
00446         while( TRUE )
00447         {
00448                 switch( *strtmp )
00449                 {
00450                         case ' ':
00451                                 *strtmp++ = '\0';
00452                                 (*argc)++;
00453                                 while( *strtmp == ' ' )
00454                                 {
00455                                         *strtmp++ = '\0';
00456                                 }
00457                                 if ( *strtmp == '\0' )
00458                                 {
00459                                         goto argc_done;
00460                                 }
00461                         break;
00462 
00463                         case '\0':
00464                         case '\n':
00465                                 *strtmp = '\0';
00466                                 (*argc)++;
00467                                 goto argc_done;
00468                         break;
00469 
00470                         default:
00471                                 strtmp++;
00472                         break;
00473                 }
00474         }
00475 argc_done:
00476         // Allocate the argv array                                      //
00477         *argv = kmalloc( (*argc) * sizeof(char *) );
00478 
00479         // Calculate the parameter string pointers                      //
00480         for( i=0; i<(*argc); i++ )
00481         {
00482                 (*argv)[i] = cmd_line;
00483                 len = strlen(cmd_line);
00484                 cmd_line += (len);
00485                 while( *(++cmd_line) == '\0' );
00486         }
00487 
00488         // Free the unused memory                                       //
00489         kfree( cmd_line );
00490         return( 0 );
00491 }
00492 
00493 //! \brief Run a program in foreground.
00494 void sh_exec(char *cmd_line)
00495 {
00496         task_t *child;
00497         int file_size;
00498         int status;
00499         int u_argc;
00500         char **u_argv;
00501 
00502         // If all goes well the u_argv array will be allocated in the   //
00503         // kernel space.                                                //
00504         if ( sh_parse_params(cmd_line, &u_argv, &u_argc) < 0 )
00505         {
00506                 kprintf("\n\rOut of virtual memory!!!");
00507                 return;
00508         }
00509 
00510         if( !u_argv )
00511         {
00512                 kprintf("file name?\n");
00513                 return;
00514         }
00515         strtoupper( u_argv[0] );
00516 
00517         // Get the file size if exists //
00518         file_size = get_file_size( u_argv[0] );
00519 
00520         if ( file_size != -1 )
00521         {
00522                 // Create the task //
00523                 child = new_task(u_argv[0], u_argc, u_argv, USER_PRIVILEGE);
00524                 if ( child == NULL )
00525                 {
00526                         // An error occurs. Treat this file as a
00527                         // simple binary 8086 code.
00528                         sh_v86_exec( u_argv[0] );
00529                         kfree( u_argv );
00530                         return;
00531                 }
00532                 // Wait until the child is killed //
00533                 waitpid(child->pid, &status, 0);
00534         }
00535         else
00536                 kprintf("\n\rFile not found!\n\r");
00537 
00538         // Free the unused memory                                       //
00539         kfree( u_argv );
00540 }
00541 
00542 //! \brief Run a program in background.
00543 void sh_bg(char *cmd_line)
00544 {
00545         int file_size;
00546         task_t *child;
00547         int u_argc;
00548         char **u_argv;
00549 
00550         // If all goes well the u_argv array will be allocated in the   //
00551         // kernel space.                                                //
00552         if ( sh_parse_params(cmd_line, &u_argv, &u_argc) < 0 )
00553         {
00554                 kprintf("\n\rOut of virtual memory!!!");
00555                 return;
00556         }
00557 
00558         if( !u_argv )
00559         {
00560                 kprintf("file name?\n");
00561                 return;
00562         }
00563         strtoupper( u_argv[0] );
00564 
00565         // Get the file size if exists //
00566         file_size = get_file_size( u_argv[0] );
00567 
00568         if ( file_size != -1 )
00569         {
00570                 // Create the task //
00571                 child = new_task(u_argv[0], u_argc, u_argv, USER_PRIVILEGE);
00572                 if ( child == NULL )
00573                 {
00574                         // An error occurs. Treat this file as a
00575                         // simple binary 8086 code.
00576                         sh_v86_bg( u_argv[0] );
00577                         kfree( u_argv );
00578                         return;
00579                 }
00580         }
00581         else
00582                 kprintf("\n\rFile not found!\n\r");
00583 
00584         // Free the unused memory                                       //
00585         kfree( u_argv );
00586 }
00587 
00588 void sh_cat(char *argv)
00589 {
00590 // Concatenate a FILE to the standard output //
00591         strtoupper(argv);
00592         if ( cat(argv) )
00593                 kprintf("\n\r");
00594         else
00595                 kprintf("\n\rFile not found!\n\r");
00596 }
00597 
00598 void sh_cd(char *argv)
00599 {
00600 // Change the current directory //
00601         strtoupper(argv);
00602         if (argv[0]=='\0') return;
00603         if ( !(cd(argv)) )
00604                 kprintf("\n\rMiniShell: cd: %s: No such directory\n\r", argv);
00605 }
00606 
00607 void sh_rm(char *argv)
00608 {
00609 // Remove a file //
00610         strtoupper(argv);
00611         if ( rm(argv) )
00612                 kprintf("Deleted!\n\r");
00613         else
00614                 kprintf("\n\rFile not found!\n\r");
00615 }
00616 
00617 void task_test()
00618 {
00619         register int cr3;
00620         __asm__ __volatile__(
00621                 "movl %%cr3, %%eax"
00622                 : "=a"(cr3) : );
00623         __asm__ __volatile__ ("" : : : "eax");
00624         kprintf("\n\rHello from task %u!!! My PDBR is @ %#010x\n\r", get_pid(), cr3);
00625         _exit( 0 );
00626 }
00627 
00628 void sh_test(char *argv)
00629 {
00630         int i;
00631         short int n;
00632 
00633         n = atoi(argv);
00634         if ( !n ) n=1;
00635         kprintf("\n\rCreating %u background tasks. Please wait.\n\r", n);
00636         for(i=0; i<n; i++)
00637         {
00638                 create_process(&task_test, &task_test, 0, "sh_task_test", KERNEL_PRIVILEGE);
00639                 kputchar('.');
00640         }
00641 }
00642 
00643 void show_cpuid()
00644 {
00645         typedef struct cache_info {
00646                 byte index;
00647                 char *string;
00648         } cache_info_t;
00649 
00650         // Cache TLB informations //
00651         static cache_info_t cache_strings[37] = {
00652                 // { 0x00, "Null descriptor" },
00653                 { 0x01, "Instruction TLB: 4KB Pages 4-way set associative, 32 entries" },
00654                 { 0x02, "Instruction TLB: 4MB Pages, 4-way set associative, 2 entries" },
00655                 { 0x03, "Data TLB: 4KB Pages, 4-way set associative, 64 entries" },
00656                 { 0x04, "Data TLB: 4MB Pages, 4-way set associative, 8 entries" },
00657                 { 0x06, "1st-level instruction cache: 8KB, 4-way set associative, 32 byte line size" },
00658                 { 0x08, "1st-level instruction cache: 16KB, 4-way set associative, 32 byte line size" },
00659                 { 0x0A, "1st-level data cache: 8KB, 2-way set associative, 32 byte line size" },
00660                 { 0x0C, "1st-level data cache: 16KB, 4-way set associative, 32 byte line size" },
00661                 { 0x22, "3rd-level cache: 512KB, 4-way set associative, dual-sectored line, 64 byte sector size" },
00662                 { 0x23, "3rd-level cache: 1MB, 8-way set associative, dual-sectored line, 64 byte sector size" },
00663                 { 0x40, "No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache" },
00664                 { 0x41, "2nd-level cache: 128KB, 4-way set associative, 32 byte line size" },
00665                 { 0x42, "2nd-level cache: 256KB, 4-way set associative, 32 byte line size" },
00666                 { 0x43, "2nd-level cache: 512KB, 4-way set associative, 32 byte line size" },
00667                 { 0x44, "2nd-level cache: 1MB, 4-way set associative, 32 byte line size" },
00668                 { 0x45, "2nd-level cache: 2MB, 4-way set associative, 32 byte line size" },
00669                 { 0x50, "Instruction TLB: 4KB and 2MB or 4MB pages, 64 entries" },
00670                 { 0x51, "Instruction TLB: 4KB and 2MB or 4MB pages, 128 entries" },
00671                 { 0x52, "Instruction TLB: 4KB and 2MB or 4MB pages, 256 entries" },
00672                 { 0x5B, "Data TLB: 4KB and 4MB pages, 64 entries" },
00673                 { 0x5C, "Data TLB: 4KB and 4MB pages, 128 entries" },
00674                 { 0x5D, "Data TLB: 4KB and 4MB pages, 256 entries" },
00675                 { 0x66, "1st-level data cache: 8KB, 4-way set associative, 64 byte line size" },
00676                 { 0x67, "1st-level data cache: 16KB, 4-way set associative, 64 byte line size" },
00677                 { 0x68, "1st-level data cache: 32KB, 4-way set associative, 64 byte line size" },
00678                 { 0x70, "Trace cache: 12K-op, 8-way set associative" },
00679                 { 0x71, "Trace cache: 16K-op, 8-way set associative" },
00680                 { 0x72, "Trace cache: 32K-op, 8-way set associative" },
00681                 { 0x79, "2nd-level cache: 128KB, 8-way set associative, dual-sectored line, 64 byte sector size" },
00682                 { 0x7A, "2nd-level cache: 256KB, 8-way set associative, dual-sectored line, 64 byte sector size" },
00683                 { 0x7B, "2nd-level cache: 512KB, 8-way set associative, dual-sectored line, 64 byte sector size" },
00684                 { 0x7C, "2nd-level cache: 1MB, 8-way set associative, dual-sectored line, 64 byte sector size" },
00685                 { 0x82, "2nd-level cache: 256KB, 8-way set associative, 32 byte line size" },
00686                 { 0x83, "2nd-level cache: 512KB, 8-way set associative, 32 byte line size" },
00687                 { 0x84, "2nd-level cache: 1MB, 8-way set associative, 32 byte line size" },
00688                 { 0x85, "2nd-level cache: 2MB, 8-way set associative, 32 byte line size" },
00689         };
00690 
00691         int eax, ebx, ecx, edx;
00692         dword vendor[4];
00693         dword i, j;
00694         int virtual;
00695         uint64_t timestamp1, timestamp2;
00696         uint32_t mhz_freq;
00697         dword IF = GET_IF();
00698 
00699         kprintf("\n\rReading CPU informations...");
00700 
00701         // Calculate the CPU frequency using the real-time clock        //
00702         disable();
00703 
00704         // Wait until the second has precisely just started             //
00705         (void)time_read();
00706         // Read the value of the current time-stamp counter (64-bit)    //
00707         __asm__ __volatile__("rdtsc" : "=A"(timestamp1));
00708         // Wait exactly a second                                        //
00709         (void)time_read();
00710         // Read the value of the current time-stamp counter again       //
00711         __asm__ __volatile__("rdtsc" : "=A"(timestamp2));
00712         // Now we can estimate the CPU frequency as follows             //
00713         mhz_freq = ((uint32_t)(timestamp2 - timestamp1))/1000000;
00714         kprintf("\n\rFrequency: %u MHz", mhz_freq);
00715 
00716         SET_IF(IF);
00717 
00718         // Execute the CPUID instruction command 0                      //
00719         cpuid(0, &eax, &ebx, &ecx, &edx);
00720 
00721         vendor[0] = ebx;
00722         vendor[1] = edx;
00723         vendor[2] = ecx;
00724         vendor[3] = 0;
00725 
00726         kprintf("\n\rDetected \"%s\" CPU", (char *)vendor);
00727 
00728         // Execute the CPUID instruction command 1 //
00729         cpuid(1, &eax, &ebx, &ecx, &edx);
00730 
00731         // Detect processor type //
00732         switch((eax >> 12) & 0x03)
00733         {
00734                 case 0:
00735                 kprintf("\n\rOriginal OEM Processor");
00736                 break;
00737 
00738                 case 1:
00739                 kprintf("\n\rIntel Overdrive(R) Processor");
00740                 break;
00741 
00742                 case 2:
00743                 kprintf("\n\rDual Processor");
00744                 break;
00745 
00746                 case 3:
00747                 kprintf("\n\r??? (reserved)");
00748                 break;
00749         }
00750         // Detect processor family & model //
00751         kprintf(        "\n\rFamily=%u Model=%u SteppingID=%u\n\r",
00752                 ((eax >> 8) & 0x0F), ((eax >> 4) & 0x0F), ((eax >> 0) & 0x0F) );
00753 
00754         // Detect with brand string //
00755         switch(ebx & 0xFF)
00756         {
00757                 case 0:
00758                 kprintf(        "Brand identification not supported\n\r"
00759                         "Processor produced before the introduction of Pentium III Xeon processor\n\r");
00760                 break;
00761 
00762                 case 1:
00763                 kprintf("Celeron\n\r");
00764                 break;
00765 
00766                 case 2:
00767                 kprintf("Pentium III\n\r");
00768                 break;
00769 
00770                 case 3:
00771                 kprintf("Pentium III Xeon\n\r");
00772                 break;
00773 
00774                 case 6:
00775                 kprintf("Pentium III Mobile\n\r");
00776                 break;
00777 
00778                 case 8:
00779                 kprintf("Pentium 4 (Willamette)\n\r");
00780                 break;
00781 
00782                 case 9:
00783                 kprintf("Pentium 4 (Northwood)\n\r");
00784                 break;
00785 
00786                 default:
00787                 kprintf("??? (processor) %u\n\r", (ebx & 0xFF));
00788                 break;
00789         }
00790 
00791         // Detect technology //
00792         if ( edx & (1<<23) ) kprintf("MMX Technology found\n\r");
00793         if ( edx & (1<<25) ) kprintf("SSE extension supported\n\r");
00794         if ( edx & (1<<26) ) kprintf("SSE2 extension supported\n\r");
00795         if ( (edx & (1<<28)) )
00796         {
00797                 virtual = ( (ebx >> 16) & 0xFF );
00798                 kprintf("Hyper-Threading Technology found (%u virtual %s)\n\r",
00799                         virtual, (virtual > 1) ? ("processors") : ("processor") );
00800         }
00801 
00802         // Detect Cache informations //
00803         do
00804         {
00805                 // Execute the CPUID instruction command 2 //
00806                 cpuid(2, &eax, &ebx, &ecx, &edx);
00807         } while ((eax & 0x0F) != 1);
00808 
00809         kprintf("\n\r- Internal cache informations -\n\r");
00810         if (!(eax & 0x80000000)) vendor[0] = (eax >> 8);
00811         if (!(ebx & 0x80000000)) vendor[1] = ebx;
00812         if (!(ecx & 0x80000000)) vendor[2] = ecx;
00813         if (!(edx & 0x80000000)) vendor[3] = edx;
00814 
00815         for (j=0; j<(sizeof(cache_strings)/sizeof(cache_info_t)); j++)
00816                 for (i=0; i<4*sizeof(dword); i++)
00817                 {
00818                         if ( ((char *)vendor)[i] != 0)
00819                                 if ( ((char *)vendor)[i]==cache_strings[j].index )
00820                                 {
00821                                         kprintf("%s\n\r", cache_strings[j].string);
00822                                         break;
00823                                 }
00824                 }
00825         kprintf("\n\r");
00826 }
00827 
00828 void sh_help(char *argv)
00829 {
00830 // Print the help //
00831         int i, row;
00832 
00833         kprintf("\n\r%s\n\r", SH_VERSION);
00834 
00835         if ( *argv != NULL )
00836         {
00837                 // Print only the selected commands //
00838                 for (i=0; i<SH_COMMANDS; i++)
00839                 if (strcmp(argv, commands[i].name)==0)
00840                 {
00841                         // Print usage and command info //
00842                         kprintf("\n\r-> ");
00843                         set_color(WHITE);
00844                         kprintf("%s", commands[i].usage);
00845                         set_color(DEFAULT_COLOR);
00846                         kprintf("\n\r   %s;\n\n\r", commands[i].help);
00847                         return;
00848                 }
00849                 // Command not found! //
00850                 kprintf("\n\r   Command not found!\n\n\r");
00851                 return;
00852         }
00853 
00854         // Print all commands //
00855         for (i=0, row=2; i<SH_COMMANDS; i++)
00856         {
00857                 // Print usage and command info //
00858                 kprintf("\n\r-> ");
00859                 set_color(WHITE);
00860                 kprintf("%s", commands[i].usage);
00861                 set_color(DEFAULT_COLOR);
00862                 kprintf("\n\r   %s;", commands[i].help);
00863 
00864                 // Wait for keypressed to avoid screen scrolling //
00865                 row += 2;
00866                 if (row >= 24)
00867                 {
00868                         if (kgetchar() == CTRL_C) break;
00869                         row = 0;
00870                 }
00871         }
00872         kprintf("\n\n\r");
00873 }
00874 
00875 void ps_task()
00876 {
00877 // This task run the command ps (processes list)                        //
00878         ps();
00879         _exit(0);
00880 }
00881 
00882 void sh_ps()
00883 {
00884         pid_t pid;
00885         int status;
00886         pid = create_process(&ps_task, &ps_task, 0, "ps", KERNEL_PRIVILEGE)->pid;
00887         waitpid(pid, &status, 0);
00888 }
00889 
00890 void sh_halt()
00891 {
00892 // Halt the system                                                      //
00893         kprintf("\n\rHalting system using APM features...");
00894         beep();
00895 
00896         sh_cd("/");
00897         sh_cd("bin");
00898         sh_v86_exec("halt.bin");
00899 
00900         // If you reach this point it means that your motherboard       //
00901         // does not support APM features...                             //
00902 
00903         // Be sure that the floppy motor has been turned off!           //
00904         out(0x03F2, 0x0C);
00905 
00906         // Halt the system                                              //
00907         kprintf("\n\rNow you can turn off power.");
00908         halt();
00909 }
00910 
00911 void sh_elf(char *argv)
00912 {
00913 // Check if the file is a valid ELF32.                                  //
00914         byte *file_buffer;
00915         int file_size;
00916 
00917         if( !argv )
00918         {
00919                 kprintf("background file?\n");
00920                 return;
00921         }
00922         strtoupper(argv);
00923 
00924         // Get the file size if exists                                  //
00925         file_size = get_file_size(argv);
00926 
00927         // Load the ELF32 file                                          //
00928         file_buffer = kmalloc(file_size);
00929         switch ( elf32_load_file(argv, file_buffer) )
00930         {
00931                 case -ENOENT:
00932                         kprintf("file not found!\n\r");
00933                 break;
00934 
00935                 case -ENOEXEC:
00936                         kprintf("not a valid ELF32 file!\n\r");
00937                 break;
00938 
00939                 default:
00940                         kprintf("ELF32 file-format OK!\n\r");
00941                 break;
00942         }
00943         kfree(file_buffer);
00944 }
00945 
00946 void shell()
00947 {
00948 // The MINIShell main program //
00949 
00950         #define SH_PROMPT       "\r[root:/fd0/%s]# "
00951         #define CMD_ARG         (cmd+strlen(commands[i].name)+1)
00952 
00953         // Shell command buffer //
00954         char cmd[STR_MAX_LENGTH];
00955         int i;
00956 
00957         // Reset the command buffer //
00958         memset(cmd, 0, sizeof(cmd));
00959 
00960         // Welcome message //
00961         set_color(DEFAULT_COLOR);
00962         kprintf("\n\rWelcome to the MiniShell (tty%u)", get_curr_task()->console);
00963         kprintf("\n\rHave a lot of fun...\n\r");
00964 
00965         // Command line //
00966         while(TRUE)
00967         {
00968                 kprintf(SH_PROMPT, pwd());
00969                 gets(cmd);
00970 
00971                 for(i=0; i<SH_COMMANDS; i++)
00972                 {
00973                         // Parse the command //
00974                         if ( strncmp(cmd, commands[i].name, strlen(commands[i].name))==0 )
00975                         {
00976                                 if (*(cmd+strlen(commands[i].name)) == '\0')
00977                                 {
00978                                         *CMD_ARG = '\0';
00979                                         break;
00980                                 }
00981                                 if (*(cmd+strlen(commands[i].name)) == ' ')
00982                                         break;
00983                         }
00984                 }
00985 
00986                 if (i == SH_COMMANDS)
00987                 {
00988                         // No command requested //
00989                         if (!cmd[0]) continue;
00990 
00991                         // Execute a file in the current path in foreground //
00992                         if( !strncmp(cmd, "./", 2) )
00993                         {
00994                                 if( cmd[2]=='\0' )
00995                                 {
00996                                         kprintf("\n%s: is a directory\n");
00997                                         continue;
00998                                 }
00999                                 else
01000                                 {
01001                                         sh_exec(cmd+2);
01002                                         continue;
01003                                 }
01004                         }
01005 
01006                         // Command not found //
01007                         kprintf("\n%s: command not found\n", cmd);
01008                         continue;
01009                 }
01010 
01011                 switch(commands[i].index)
01012                 {
01013                         case SH_HELP:
01014                         sh_help(CMD_ARG);
01015                         break;
01016 
01017                         case SH_UNAME:
01018                         kprintf("\n\r%s - Kernel [v%s]\n\r", KERNEL_NAME, KERNEL_VERSION);
01019                         break;
01020 
01021                         case SH_CLEAR:
01022                         set_color(DEFAULT_COLOR);
01023                         clrscr();
01024                         break;
01025 
01026                         case SH_REBOOT:
01027                         reboot();
01028                         break;
01029 
01030                         case SH_DUMP:
01031                         breakpoint();
01032                         break;
01033 
01034                         case SH_READ:
01035                         sh_read(CMD_ARG);
01036                         break;
01037 
01038                         case SH_WRITE:
01039                         sh_write(CMD_ARG);
01040                         break;
01041 
01042                         case SH_PAGES:
01043                         dump_dirty_pages();
01044                         break;
01045 
01046                         case SH_MEM:
01047                         dump_memory_map();
01048                         break;
01049 
01050                         case SH_CHECKMEM:
01051                         create_process(
01052                                 &check_free_frames_integrity,
01053                                 &check_free_frames_integrity,
01054                                 0,
01055                                 "frames_check",
01056                                 KERNEL_PRIVILEGE
01057                         );
01058                         break;
01059 
01060                         case SH_FRAMES:
01061                         dump_free_frames();
01062                         break;
01063 
01064                         case SH_EXEC:
01065                         sh_exec(CMD_ARG);
01066                         break;
01067 
01068                         case SH_BG:
01069                         sh_bg(CMD_ARG);
01070                         break;
01071 
01072                         case SH_V86EXEC:
01073                         sh_v86_exec(CMD_ARG);
01074                         break;
01075 
01076                         case SH_V86BG:
01077                         sh_v86_bg(CMD_ARG);
01078                         break;
01079 
01080                         case SH_TEST:
01081                         sh_test(CMD_ARG);
01082                         break;
01083 
01084                         case SH_CPUID:
01085                         show_cpuid();
01086                         break;
01087 
01088                         case SH_MOUNT:
01089                         Read_FAT();
01090                         break;
01091 
01092                         case SH_LS:
01093                         ls();
01094                         break;
01095 
01096                         case SH_CAT:
01097                         sh_cat(CMD_ARG);
01098                         break;
01099 
01100                         case SH_CD:
01101                         sh_cd(CMD_ARG);
01102                         break;
01103 
01104                         case SH_RM:
01105                         sh_rm(CMD_ARG);
01106                         break;
01107 
01108                         case SH_PS:
01109                         sh_ps();
01110                         break;
01111 
01112                         case SH_KILL:
01113                         sh_kill(CMD_ARG);
01114                         break;
01115 
01116                         case SH_RS232:
01117                         rs232_chat(CMD_ARG);
01118                         break;
01119 
01120                         case SH_PCISCAN:
01121                         pci_scan();
01122                         break;
01123 
01124                         case SH_RTL8139_INIT:
01125                         ifconfig(CMD_ARG);
01126                         break;
01127 
01128                         case SH_ETH_PING:
01129                         ping(CMD_ARG);
01130                         break;
01131 
01132                         case SH_ETH_ARP:
01133                         arp_request(CMD_ARG);
01134                         break;
01135 
01136                         case SH_HALT:
01137                         sh_halt();
01138                         break;
01139 
01140                         case SH_ELF:
01141                         sh_elf(CMD_ARG);
01142                         break;
01143 
01144                         // **************** Luca Giovacchini (Ide) ****************
01145                         case SH_IDETEST:
01146                                 Sh_IdeTest();
01147                                 break;
01148                         case SH_IDEREAD:
01149                                 Sh_IdeRead();
01150                                 break;
01151                         case SH_IDEWRITE:
01152                                 Sh_IdeWrite();
01153                                 break;
01154                         case SH_IDEDEVICEINFO:
01155                                 Sh_IdeDeviceInfo();
01156                                 break;
01157                         // ********************************************************
01158 
01159                         // ******************** Filippo Brogi *********************
01160                         case SH_LS_EXT2:
01161                                 ls_ext2();
01162                         break;
01163 
01164                         case SH_CD_EXT2:
01165                                 sh_cd2(CMD_ARG);
01166                         break;
01167 
01168                         case SH_CAT_EXT2:
01169                                 sh_cat2(CMD_ARG);
01170                         break;
01171                         // ********************************************************
01172 
01173                         case SH_TIME:
01174                                 kprintf("\r%u\n\r", time_read());
01175                         break;
01176                 }
01177         }
01178 }

Generated on Fri Feb 20 15:32:16 2004 for Minirighi by doxygen1.2.18