Subversion Repositories HelenOS-historic

Rev

Rev 677 | Rev 775 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2005 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /**
  30.  * This file is meant to contain all wrapper functions for
  31.  * all kconsole commands. The point is in separating
  32.  * kconsole specific wrappers from kconsole-unaware functions
  33.  * from other subsystems.
  34.  */
  35.  
  36. #include <console/cmd.h>
  37. #include <console/kconsole.h>
  38. #include <print.h>
  39. #include <panic.h>
  40. #include <typedefs.h>
  41. #include <arch/types.h>
  42. #include <list.h>
  43. #include <arch.h>
  44. #include <func.h>
  45. #include <macros.h>
  46. #include <debug.h>
  47. #include <symtab.h>
  48. #include <cpu.h>
  49. #include <mm/tlb.h>
  50. #include <arch/mm/tlb.h>
  51. #include <mm/frame.h>
  52. #include <main/version.h>
  53. #include <mm/slab.h>
  54.  
  55. /** Data and methods for 'help' command. */
  56. static int cmd_help(cmd_arg_t *argv);
  57. static cmd_info_t help_info = {
  58.     .name = "help",
  59.     .description = "List of supported commands.",
  60.     .func = cmd_help,
  61.     .argc = 0
  62. };
  63.  
  64. static cmd_info_t exit_info = {
  65.     .name = "exit",
  66.     .description ="Exit kconsole",
  67.     .argc = 0
  68. };
  69.  
  70. /** Data and methods for 'description' command. */
  71. static int cmd_desc(cmd_arg_t *argv);
  72. static void desc_help(void);
  73. static char desc_buf[MAX_CMDLINE+1];
  74. static cmd_arg_t desc_argv = {
  75.     .type = ARG_TYPE_STRING,
  76.     .buffer = desc_buf,
  77.     .len = sizeof(desc_buf)
  78. };
  79. static cmd_info_t desc_info = {
  80.     .name = "describe",
  81.     .description = "Describe specified command.",
  82.     .help = desc_help,
  83.     .func = cmd_desc,
  84.     .argc = 1,
  85.     .argv = &desc_argv
  86. };
  87.  
  88. /** Data and methods for 'symaddr' command. */
  89. static int cmd_symaddr(cmd_arg_t *argv);
  90. static char symaddr_buf[MAX_CMDLINE+1];
  91. static cmd_arg_t symaddr_argv = {
  92.     .type = ARG_TYPE_STRING,
  93.     .buffer = symaddr_buf,
  94.     .len = sizeof(symaddr_buf)
  95. };
  96. static cmd_info_t symaddr_info = {
  97.     .name = "symaddr",
  98.     .description = "Return symbol address.",
  99.     .func = cmd_symaddr,
  100.     .argc = 1,
  101.     .argv = &symaddr_argv
  102. };
  103.  
  104. static char set_buf[MAX_CMDLINE+1];
  105. static int cmd_set4(cmd_arg_t *argv);
  106. static cmd_arg_t set4_argv[] = {
  107.     {
  108.         .type = ARG_TYPE_STRING,
  109.         .buffer = set_buf,
  110.         .len = sizeof(set_buf)
  111.     },
  112.     {
  113.         .type = ARG_TYPE_INT
  114.     }
  115. };
  116. static cmd_info_t set4_info = {
  117.     .name = "set4",
  118.     .description = "set <dest_addr> <value> - 4byte version",
  119.     .func = cmd_set4,
  120.     .argc = 2,
  121.     .argv = set4_argv
  122. };
  123.  
  124. /** Data and methods for 'call0' command. */
  125. static char call0_buf[MAX_CMDLINE+1];
  126. static char carg1_buf[MAX_CMDLINE+1];
  127. static char carg2_buf[MAX_CMDLINE+1];
  128. static char carg3_buf[MAX_CMDLINE+1];
  129.  
  130. static int cmd_call0(cmd_arg_t *argv);
  131. static cmd_arg_t call0_argv = {
  132.     .type = ARG_TYPE_STRING,
  133.     .buffer = call0_buf,
  134.     .len = sizeof(call0_buf)
  135. };
  136. static cmd_info_t call0_info = {
  137.     .name = "call0",
  138.     .description = "call0 <function> -> call function().",
  139.     .func = cmd_call0,
  140.     .argc = 1,
  141.     .argv = &call0_argv
  142. };
  143.  
  144. /** Data and methods for 'call1' command. */
  145. static int cmd_call1(cmd_arg_t *argv);
  146. static cmd_arg_t call1_argv[] = {
  147.     {
  148.         .type = ARG_TYPE_STRING,
  149.         .buffer = call0_buf,
  150.         .len = sizeof(call0_buf)
  151.     },
  152.     {
  153.         .type = ARG_TYPE_VAR,
  154.         .buffer = carg1_buf,
  155.         .len = sizeof(carg1_buf)
  156.     }
  157. };
  158. static cmd_info_t call1_info = {
  159.     .name = "call1",
  160.     .description = "call1 <function> <arg1> -> call function(arg1).",
  161.     .func = cmd_call1,
  162.     .argc = 2,
  163.     .argv = call1_argv
  164. };
  165.  
  166. /** Data and methods for 'call2' command. */
  167. static int cmd_call2(cmd_arg_t *argv);
  168. static cmd_arg_t call2_argv[] = {
  169.     {
  170.         .type = ARG_TYPE_STRING,
  171.         .buffer = call0_buf,
  172.         .len = sizeof(call0_buf)
  173.     },
  174.     {
  175.         .type = ARG_TYPE_VAR,
  176.         .buffer = carg1_buf,
  177.         .len = sizeof(carg1_buf)
  178.     },
  179.     {
  180.         .type = ARG_TYPE_VAR,
  181.         .buffer = carg2_buf,
  182.         .len = sizeof(carg2_buf)
  183.     }
  184. };
  185. static cmd_info_t call2_info = {
  186.     .name = "call2",
  187.     .description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
  188.     .func = cmd_call2,
  189.     .argc = 3,
  190.     .argv = call2_argv
  191. };
  192.  
  193. /** Data and methods for 'call3' command. */
  194. static int cmd_call3(cmd_arg_t *argv);
  195. static cmd_arg_t call3_argv[] = {
  196.     {
  197.         .type = ARG_TYPE_STRING,
  198.         .buffer = call0_buf,
  199.         .len = sizeof(call0_buf)
  200.     },
  201.     {
  202.         .type = ARG_TYPE_VAR,
  203.         .buffer = carg1_buf,
  204.         .len = sizeof(carg1_buf)
  205.     },
  206.     {
  207.         .type = ARG_TYPE_VAR,
  208.         .buffer = carg2_buf,
  209.         .len = sizeof(carg2_buf)
  210.     },
  211.     {
  212.         .type = ARG_TYPE_VAR,
  213.         .buffer = carg3_buf,
  214.         .len = sizeof(carg3_buf)
  215.     }
  216.  
  217. };
  218. static cmd_info_t call3_info = {
  219.     .name = "call3",
  220.     .description = "call3 <function> <arg1> <arg2> <arg3> -> call function(arg1,arg2,arg3).",
  221.     .func = cmd_call3,
  222.     .argc = 4,
  223.     .argv = call3_argv
  224. };
  225.  
  226. /** Data and methods for 'halt' command. */
  227. static int cmd_halt(cmd_arg_t *argv);
  228. static cmd_info_t halt_info = {
  229.     .name = "halt",
  230.     .description = "Halt the kernel.",
  231.     .func = cmd_halt,
  232.     .argc = 0
  233. };
  234.  
  235. /** Data and methods for 'tlb' command. */
  236. static int cmd_tlb(cmd_arg_t *argv);
  237. cmd_info_t tlb_info = {
  238.     .name = "tlb",
  239.     .description = "Print TLB of current processor.",
  240.     .help = NULL,
  241.     .func = cmd_tlb,
  242.     .argc = 0,
  243.     .argv = NULL
  244. };
  245.  
  246.  
  247. static int cmd_slabs(cmd_arg_t *argv);
  248. static cmd_info_t slabs_info = {
  249.     .name = "slabs",
  250.     .description = "List SLAB caches.",
  251.     .func = cmd_slabs,
  252.     .argc = 0
  253. };
  254.  
  255. /** Data and methods for 'zones' command */
  256. static int cmd_zones(cmd_arg_t *argv);
  257. static cmd_info_t zones_info = {
  258.     .name = "zones",
  259.     .description = "List of memory zones.",
  260.     .func = cmd_zones,
  261.     .argc = 0
  262. };
  263.  
  264. /** Data and methods for 'zone' command */
  265. static int cmd_zone(cmd_arg_t *argv);
  266. static cmd_arg_t zone_argv = {
  267.     .type = ARG_TYPE_INT,
  268. };
  269.  
  270. static cmd_info_t zone_info = {
  271.     .name = "zone",
  272.     .description = "Show memory zone structure.",
  273.     .func = cmd_zone,
  274.     .argc = 1,
  275.     .argv = &zone_argv
  276. };
  277.  
  278. /** Data and methods for 'cpus' command. */
  279. static int cmd_cpus(cmd_arg_t *argv);
  280. cmd_info_t cpus_info = {
  281.     .name = "cpus",
  282.     .description = "List all processors.",
  283.     .help = NULL,
  284.     .func = cmd_cpus,
  285.     .argc = 0,
  286.     .argv = NULL
  287. };
  288.  
  289. /** Data and methods for 'version' command. */
  290. static int cmd_version(cmd_arg_t *argv);
  291. cmd_info_t version_info = {
  292.     .name = "version",
  293.     .description = "Print version information.",
  294.     .help = NULL,
  295.     .func = cmd_version,
  296.     .argc = 0,
  297.     .argv = NULL
  298. };
  299.  
  300.  
  301.  
  302.  
  303. /** Initialize command info structure.
  304.  *
  305.  * @param cmd Command info structure.
  306.  *
  307.  */
  308. void cmd_initialize(cmd_info_t *cmd)
  309. {
  310.     spinlock_initialize(&cmd->lock, "cmd");
  311.     link_initialize(&cmd->link);
  312. }
  313.  
  314. /** Initialize and register commands. */
  315. void cmd_init(void)
  316. {
  317.     cmd_initialize(&help_info);
  318.     if (!cmd_register(&help_info))
  319.         panic("could not register command %s\n", help_info.name);
  320.  
  321.     cmd_initialize(&desc_info);
  322.     if (!cmd_register(&desc_info))
  323.         panic("could not register command %s\n", desc_info.name);
  324.  
  325.     cmd_initialize(&exit_info);
  326.     if (!cmd_register(&exit_info))
  327.         panic("could not register command %s\n", exit_info.name);
  328.    
  329.     cmd_initialize(&symaddr_info);
  330.     if (!cmd_register(&symaddr_info))
  331.         panic("could not register command %s\n", symaddr_info.name);
  332.  
  333.     cmd_initialize(&call0_info);
  334.     if (!cmd_register(&call0_info))
  335.         panic("could not register command %s\n", call0_info.name);
  336.  
  337.     cmd_initialize(&call1_info);
  338.     if (!cmd_register(&call1_info))
  339.         panic("could not register command %s\n", call1_info.name);
  340.  
  341.     cmd_initialize(&call2_info);
  342.     if (!cmd_register(&call2_info))
  343.         panic("could not register command %s\n", call2_info.name);
  344.  
  345.     cmd_initialize(&call3_info);
  346.     if (!cmd_register(&call3_info))
  347.         panic("could not register command %s\n", call3_info.name);
  348.  
  349.     cmd_initialize(&set4_info);
  350.     if (!cmd_register(&set4_info))
  351.         panic("could not register command %s\n", set4_info.name);
  352.    
  353.     cmd_initialize(&halt_info);
  354.     if (!cmd_register(&halt_info))
  355.         panic("could not register command %s\n", halt_info.name);
  356.  
  357.     cmd_initialize(&tlb_info);
  358.     if (!cmd_register(&tlb_info))
  359.         panic("could not register command %s\n", tlb_info.name);
  360.  
  361.     cmd_initialize(&zones_info);
  362.     if (!cmd_register(&zones_info))
  363.         panic("could not register command %s\n", zones_info.name);
  364.  
  365.     cmd_initialize(&slabs_info);
  366.     if (!cmd_register(&slabs_info))
  367.         panic("could not register command %s\n", slabs_info.name);
  368.  
  369.     cmd_initialize(&zone_info);
  370.     if (!cmd_register(&zone_info))
  371.         panic("could not register command %s\n", zone_info.name);
  372.  
  373.     cmd_initialize(&cpus_info);
  374.     if (!cmd_register(&cpus_info))
  375.         panic("could not register command %s\n", cpus_info.name);
  376.        
  377.     cmd_initialize(&version_info);
  378.     if (!cmd_register(&version_info))
  379.         panic("could not register command %s\n", version_info.name);
  380.        
  381.        
  382.  
  383. }
  384.  
  385.  
  386. /** List supported commands.
  387.  *
  388.  * @param argv Argument vector.
  389.  *
  390.  * @return 0 on failure, 1 on success.
  391.  */
  392. int cmd_help(cmd_arg_t *argv)
  393. {
  394.     link_t *cur;
  395.  
  396.     spinlock_lock(&cmd_lock);
  397.    
  398.     for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
  399.         cmd_info_t *hlp;
  400.        
  401.         hlp = list_get_instance(cur, cmd_info_t, link);
  402.         spinlock_lock(&hlp->lock);
  403.        
  404.         printf("%s - %s\n", hlp->name, hlp->description);
  405.  
  406.         spinlock_unlock(&hlp->lock);
  407.     }
  408.    
  409.     spinlock_unlock(&cmd_lock);
  410.  
  411.     return 1;
  412. }
  413.  
  414. /** Describe specified command.
  415.  *
  416.  * @param argv Argument vector.
  417.  *
  418.  * @return 0 on failure, 1 on success.
  419.  */
  420. int cmd_desc(cmd_arg_t *argv)
  421. {
  422.     link_t *cur;
  423.  
  424.     spinlock_lock(&cmd_lock);
  425.    
  426.     for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
  427.         cmd_info_t *hlp;
  428.        
  429.         hlp = list_get_instance(cur, cmd_info_t, link);
  430.         spinlock_lock(&hlp->lock);
  431.  
  432.         if (strncmp(hlp->name, (const char *) argv->buffer, strlen(hlp->name)) == 0) {
  433.             printf("%s - %s\n", hlp->name, hlp->description);
  434.             if (hlp->help)
  435.                 hlp->help();
  436.             spinlock_unlock(&hlp->lock);
  437.             break;
  438.         }
  439.  
  440.         spinlock_unlock(&hlp->lock);
  441.     }
  442.    
  443.     spinlock_unlock(&cmd_lock);
  444.  
  445.     return 1;
  446. }
  447.  
  448. /** Search symbol table */
  449. int cmd_symaddr(cmd_arg_t *argv)
  450. {
  451.     symtab_print_search(argv->buffer);
  452.    
  453.     return 1;
  454. }
  455.  
  456. /** Call function with zero parameters */
  457. int cmd_call0(cmd_arg_t *argv)
  458. {
  459.     __address symaddr;
  460.     char *symbol;
  461.     __native (*f)(void);
  462.  
  463.     symaddr = get_symbol_addr(argv->buffer);
  464.     if (!symaddr)
  465.         printf("Symbol %s not found.\n", argv->buffer);
  466.     else if (symaddr == (__address) -1) {
  467.         symtab_print_search(argv->buffer);
  468.         printf("Duplicate symbol, be more specific.\n");
  469.     } else {
  470.         symbol = get_symtab_entry(symaddr);
  471.         printf("Calling f(): 0x%p: %s\n", symaddr, symbol);
  472.         f =  (__native (*)(void)) symaddr;
  473.         printf("Result: 0x%p\n", f());
  474.     }
  475.    
  476.     return 1;
  477. }
  478.  
  479. /** Call function with one parameter */
  480. int cmd_call1(cmd_arg_t *argv)
  481. {
  482.     __address symaddr;
  483.     char *symbol;
  484.     __native (*f)(__native);
  485.     __native arg1 = argv[1].intval;
  486.  
  487.     symaddr = get_symbol_addr(argv->buffer);
  488.     if (!symaddr)
  489.         printf("Symbol %s not found.\n", argv->buffer);
  490.     else if (symaddr == (__address) -1) {
  491.         symtab_print_search(argv->buffer);
  492.         printf("Duplicate symbol, be more specific.\n");
  493.     } else {
  494.         symbol = get_symtab_entry(symaddr);
  495.         printf("Calling f(0x%x): 0x%p: %s\n", arg1, symaddr, symbol);
  496.         f =  (__native (*)(__native)) symaddr;
  497.         printf("Result: 0x%p\n", f(arg1));
  498.     }
  499.    
  500.     return 1;
  501. }
  502.  
  503. /** Call function with two parameters */
  504. int cmd_call2(cmd_arg_t *argv)
  505. {
  506.     __address symaddr;
  507.     char *symbol;
  508.     __native (*f)(__native,__native);
  509.     __native arg1 = argv[1].intval;
  510.     __native arg2 = argv[2].intval;
  511.  
  512.     symaddr = get_symbol_addr(argv->buffer);
  513.     if (!symaddr)
  514.         printf("Symbol %s not found.\n", argv->buffer);
  515.     else if (symaddr == (__address) -1) {
  516.         symtab_print_search(argv->buffer);
  517.         printf("Duplicate symbol, be more specific.\n");
  518.     } else {
  519.         symbol = get_symtab_entry(symaddr);
  520.         printf("Calling f(0x%x,0x%x): 0x%p: %s\n",
  521.                arg1, arg2, symaddr, symbol);
  522.         f =  (__native (*)(__native,__native)) symaddr;
  523.         printf("Result: 0x%p\n", f(arg1, arg2));
  524.     }
  525.    
  526.     return 1;
  527. }
  528.  
  529. /** Call function with three parameters */
  530. int cmd_call3(cmd_arg_t *argv)
  531. {
  532.     __address symaddr;
  533.     char *symbol;
  534.     __native (*f)(__native,__native,__native);
  535.     __native arg1 = argv[1].intval;
  536.     __native arg2 = argv[2].intval;
  537.     __native arg3 = argv[3].intval;
  538.  
  539.     symaddr = get_symbol_addr(argv->buffer);
  540.     if (!symaddr)
  541.         printf("Symbol %s not found.\n", argv->buffer);
  542.     else if (symaddr == (__address) -1) {
  543.         symtab_print_search(argv->buffer);
  544.         printf("Duplicate symbol, be more specific.\n");
  545.     } else {
  546.         symbol = get_symtab_entry(symaddr);
  547.         printf("Calling f(0x%x,0x%x, 0x%x): 0x%p: %s\n",
  548.                arg1, arg2, arg3, symaddr, symbol);
  549.         f =  (__native (*)(__native,__native,__native)) symaddr;
  550.         printf("Result: 0x%p\n", f(arg1, arg2, arg3));
  551.     }
  552.    
  553.     return 1;
  554. }
  555.  
  556.  
  557. /** Print detailed description of 'describe' command. */
  558. void desc_help(void)
  559. {
  560.     printf("Syntax: describe command_name\n");
  561. }
  562.  
  563. /** Halt the kernel.
  564.  *
  565.  * @param argv Argument vector (ignored).
  566.  *
  567.  * @return 0 on failure, 1 on success (never returns).
  568.  */
  569. int cmd_halt(cmd_arg_t *argv)
  570. {
  571.     halt();
  572.     return 1;
  573. }
  574.  
  575. /** Command for printing TLB contents.
  576.  *
  577.  * @param argv Not used.
  578.  *
  579.  * @return Always returns 1.
  580.  */
  581. int cmd_tlb(cmd_arg_t *argv)
  582. {
  583.     tlb_print();
  584.     return 1;
  585. }
  586.  
  587. /** Write 4 byte value to address */
  588. int cmd_set4(cmd_arg_t *argv)
  589. {
  590.     __u32 *addr ;
  591.     __u32 arg1 = argv[1].intval;
  592.     bool pointer = false;
  593.  
  594.     if (((char *)argv->buffer)[0] == '*') {
  595.         addr = (__u32 *) get_symbol_addr(argv->buffer+1);
  596.         pointer = true;
  597.     } else if (((char *)argv->buffer)[0] >= '0' &&
  598.            ((char *)argv->buffer)[0] <= '9')
  599.         addr = (__u32 *)atoi((char *)argv->buffer);
  600.     else
  601.         addr = (__u32 *)get_symbol_addr(argv->buffer);
  602.  
  603.     if (!addr)
  604.         printf("Symbol %s not found.\n", argv->buffer);
  605.     else if (addr == (__u32 *) -1) {
  606.         symtab_print_search(argv->buffer);
  607.         printf("Duplicate symbol, be more specific.\n");
  608.     } else {
  609.         if (pointer)
  610.             addr = (__u32 *)(*(__native *)addr);
  611.         printf("Writing 0x%x -> 0x%p\n", arg1, addr);
  612.         *addr = arg1;
  613.        
  614.     }
  615.    
  616.     return 1;
  617. }
  618.  
  619. /** Command for listings SLAB caches
  620.  *
  621.  * @param argv Ignores
  622.  *
  623.  * @return Always 1
  624.  */
  625. int cmd_slabs(cmd_arg_t * argv) {
  626.     slab_print_list();
  627.     return 1;
  628. }
  629.  
  630. /** Command for listing memory zones
  631.  *
  632.  * @param argv Ignored
  633.  *
  634.  * return Always 1
  635.  */
  636. int cmd_zones(cmd_arg_t * argv) {
  637.     zone_print_list();
  638.     return 1;
  639. }
  640.  
  641. /** Command for memory zone details
  642.  *
  643.  * @param argv Integer argument from cmdline expected
  644.  *
  645.  * return Always 1
  646.  */
  647. int cmd_zone(cmd_arg_t * argv) {
  648.     zone_print_one(argv[0].intval);
  649.     return 1;
  650. }
  651.  
  652. /** Command for listing processors.
  653.  *
  654.  * @param argv Ignored.
  655.  *
  656.  * return Always 1.
  657.  */
  658. int cmd_cpus(cmd_arg_t *argv)
  659. {
  660.     cpu_list();
  661.     return 1;
  662. }
  663.  
  664. /** Command for printing kernel version.
  665.  *
  666.  * @param argv Ignored.
  667.  *
  668.  * return Always 1.
  669.  */
  670. int cmd_version(cmd_arg_t *argv)
  671. {
  672.     version_print();
  673.     return 1;
  674. }
  675.