Subversion Repositories HelenOS

Rev

Rev 1888 | Rev 2019 | 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. /** @addtogroup genericconsole
  30.  * @{
  31.  */
  32.  
  33. /**
  34.  * @file    cmd.c
  35.  * @brief   Kernel console command wrappers.
  36.  *
  37.  * This file is meant to contain all wrapper functions for
  38.  * all kconsole commands. The point is in separating
  39.  * kconsole specific wrappers from kconsole-unaware functions
  40.  * from other subsystems.
  41.  */
  42.  
  43. #include <console/cmd.h>
  44. #include <console/console.h>
  45. #include <console/kconsole.h>
  46. #include <print.h>
  47. #include <panic.h>
  48. #include <typedefs.h>
  49. #include <arch/types.h>
  50. #include <adt/list.h>
  51. #include <arch.h>
  52. #include <func.h>
  53. #include <macros.h>
  54. #include <debug.h>
  55. #include <symtab.h>
  56. #include <cpu.h>
  57. #include <mm/tlb.h>
  58. #include <arch/mm/tlb.h>
  59. #include <mm/frame.h>
  60. #include <main/version.h>
  61. #include <mm/slab.h>
  62. #include <proc/scheduler.h>
  63. #include <proc/thread.h>
  64. #include <proc/task.h>
  65. #include <ipc/ipc.h>
  66. #include <ipc/irq.h>
  67.  
  68. /* Data and methods for 'help' command. */
  69. static int cmd_help(cmd_arg_t *argv);
  70. static cmd_info_t help_info = {
  71.     .name = "help",
  72.     .description = "List of supported commands.",
  73.     .func = cmd_help,
  74.     .argc = 0
  75. };
  76.  
  77. static cmd_info_t exit_info = {
  78.     .name = "exit",
  79.     .description ="Exit kconsole",
  80.     .argc = 0
  81. };
  82.  
  83. static int cmd_continue(cmd_arg_t *argv);
  84. static cmd_info_t continue_info = {
  85.     .name = "continue",
  86.     .description ="Return console back to userspace.",
  87.     .func = cmd_continue,
  88.     .argc = 0
  89. };
  90.  
  91. /* Data and methods for 'description' command. */
  92. static int cmd_desc(cmd_arg_t *argv);
  93. static void desc_help(void);
  94. static char desc_buf[MAX_CMDLINE+1];
  95. static cmd_arg_t desc_argv = {
  96.     .type = ARG_TYPE_STRING,
  97.     .buffer = desc_buf,
  98.     .len = sizeof(desc_buf)
  99. };
  100. static cmd_info_t desc_info = {
  101.     .name = "describe",
  102.     .description = "Describe specified command.",
  103.     .help = desc_help,
  104.     .func = cmd_desc,
  105.     .argc = 1,
  106.     .argv = &desc_argv
  107. };
  108.  
  109. /* Data and methods for 'symaddr' command. */
  110. static int cmd_symaddr(cmd_arg_t *argv);
  111. static char symaddr_buf[MAX_CMDLINE+1];
  112. static cmd_arg_t symaddr_argv = {
  113.     .type = ARG_TYPE_STRING,
  114.     .buffer = symaddr_buf,
  115.     .len = sizeof(symaddr_buf)
  116. };
  117. static cmd_info_t symaddr_info = {
  118.     .name = "symaddr",
  119.     .description = "Return symbol address.",
  120.     .func = cmd_symaddr,
  121.     .argc = 1,
  122.     .argv = &symaddr_argv
  123. };
  124.  
  125. static char set_buf[MAX_CMDLINE+1];
  126. static int cmd_set4(cmd_arg_t *argv);
  127. static cmd_arg_t set4_argv[] = {
  128.     {
  129.         .type = ARG_TYPE_STRING,
  130.         .buffer = set_buf,
  131.         .len = sizeof(set_buf)
  132.     },
  133.     {
  134.         .type = ARG_TYPE_INT
  135.     }
  136. };
  137. static cmd_info_t set4_info = {
  138.     .name = "set4",
  139.     .description = "set <dest_addr> <value> - 4byte version",
  140.     .func = cmd_set4,
  141.     .argc = 2,
  142.     .argv = set4_argv
  143. };
  144.  
  145. /* Data and methods for 'call0' command. */
  146. static char call0_buf[MAX_CMDLINE+1];
  147. static char carg1_buf[MAX_CMDLINE+1];
  148. static char carg2_buf[MAX_CMDLINE+1];
  149. static char carg3_buf[MAX_CMDLINE+1];
  150.  
  151. static int cmd_call0(cmd_arg_t *argv);
  152. static cmd_arg_t call0_argv = {
  153.     .type = ARG_TYPE_STRING,
  154.     .buffer = call0_buf,
  155.     .len = sizeof(call0_buf)
  156. };
  157. static cmd_info_t call0_info = {
  158.     .name = "call0",
  159.     .description = "call0 <function> -> call function().",
  160.     .func = cmd_call0,
  161.     .argc = 1,
  162.     .argv = &call0_argv
  163. };
  164.  
  165. /* Data and methods for 'call1' command. */
  166. static int cmd_call1(cmd_arg_t *argv);
  167. static cmd_arg_t call1_argv[] = {
  168.     {
  169.         .type = ARG_TYPE_STRING,
  170.         .buffer = call0_buf,
  171.         .len = sizeof(call0_buf)
  172.     },
  173.     {
  174.         .type = ARG_TYPE_VAR,
  175.         .buffer = carg1_buf,
  176.         .len = sizeof(carg1_buf)
  177.     }
  178. };
  179. static cmd_info_t call1_info = {
  180.     .name = "call1",
  181.     .description = "call1 <function> <arg1> -> call function(arg1).",
  182.     .func = cmd_call1,
  183.     .argc = 2,
  184.     .argv = call1_argv
  185. };
  186.  
  187. /* Data and methods for 'call2' command. */
  188. static int cmd_call2(cmd_arg_t *argv);
  189. static cmd_arg_t call2_argv[] = {
  190.     {
  191.         .type = ARG_TYPE_STRING,
  192.         .buffer = call0_buf,
  193.         .len = sizeof(call0_buf)
  194.     },
  195.     {
  196.         .type = ARG_TYPE_VAR,
  197.         .buffer = carg1_buf,
  198.         .len = sizeof(carg1_buf)
  199.     },
  200.     {
  201.         .type = ARG_TYPE_VAR,
  202.         .buffer = carg2_buf,
  203.         .len = sizeof(carg2_buf)
  204.     }
  205. };
  206. static cmd_info_t call2_info = {
  207.     .name = "call2",
  208.     .description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
  209.     .func = cmd_call2,
  210.     .argc = 3,
  211.     .argv = call2_argv
  212. };
  213.  
  214. /* Data and methods for 'call3' command. */
  215. static int cmd_call3(cmd_arg_t *argv);
  216. static cmd_arg_t call3_argv[] = {
  217.     {
  218.         .type = ARG_TYPE_STRING,
  219.         .buffer = call0_buf,
  220.         .len = sizeof(call0_buf)
  221.     },
  222.     {
  223.         .type = ARG_TYPE_VAR,
  224.         .buffer = carg1_buf,
  225.         .len = sizeof(carg1_buf)
  226.     },
  227.     {
  228.         .type = ARG_TYPE_VAR,
  229.         .buffer = carg2_buf,
  230.         .len = sizeof(carg2_buf)
  231.     },
  232.     {
  233.         .type = ARG_TYPE_VAR,
  234.         .buffer = carg3_buf,
  235.         .len = sizeof(carg3_buf)
  236.     }
  237.  
  238. };
  239. static cmd_info_t call3_info = {
  240.     .name = "call3",
  241.     .description = "call3 <function> <arg1> <arg2> <arg3> -> call function(arg1,arg2,arg3).",
  242.     .func = cmd_call3,
  243.     .argc = 4,
  244.     .argv = call3_argv
  245. };
  246.  
  247. /* Data and methods for 'halt' command. */
  248. static int cmd_halt(cmd_arg_t *argv);
  249. static cmd_info_t halt_info = {
  250.     .name = "halt",
  251.     .description = "Halt the kernel.",
  252.     .func = cmd_halt,
  253.     .argc = 0
  254. };
  255.  
  256. /* Data and methods for 'tlb' command. */
  257. static int cmd_tlb(cmd_arg_t *argv);
  258. cmd_info_t tlb_info = {
  259.     .name = "tlb",
  260.     .description = "Print TLB of current processor.",
  261.     .help = NULL,
  262.     .func = cmd_tlb,
  263.     .argc = 0,
  264.     .argv = NULL
  265. };
  266.  
  267. static int cmd_threads(cmd_arg_t *argv);
  268. static cmd_info_t threads_info = {
  269.     .name = "threads",
  270.     .description = "List all threads.",
  271.     .func = cmd_threads,
  272.     .argc = 0
  273. };
  274.  
  275. static int cmd_tasks(cmd_arg_t *argv);
  276. static cmd_info_t tasks_info = {
  277.     .name = "tasks",
  278.     .description = "List all tasks.",
  279.     .func = cmd_tasks,
  280.     .argc = 0
  281. };
  282.  
  283.  
  284. static int cmd_sched(cmd_arg_t *argv);
  285. static cmd_info_t sched_info = {
  286.     .name = "scheduler",
  287.     .description = "List all scheduler information.",
  288.     .func = cmd_sched,
  289.     .argc = 0
  290. };
  291.  
  292. static int cmd_slabs(cmd_arg_t *argv);
  293. static cmd_info_t slabs_info = {
  294.     .name = "slabs",
  295.     .description = "List slab caches.",
  296.     .func = cmd_slabs,
  297.     .argc = 0
  298. };
  299.  
  300. /* Data and methods for 'zones' command */
  301. static int cmd_zones(cmd_arg_t *argv);
  302. static cmd_info_t zones_info = {
  303.     .name = "zones",
  304.     .description = "List of memory zones.",
  305.     .func = cmd_zones,
  306.     .argc = 0
  307. };
  308.  
  309. /* Data and methods for 'ipc_task' command */
  310. static int cmd_ipc_task(cmd_arg_t *argv);
  311. static cmd_arg_t ipc_task_argv = {
  312.     .type = ARG_TYPE_INT,
  313. };
  314. static cmd_info_t ipc_task_info = {
  315.     .name = "ipc_task",
  316.     .description = "ipc_task <taskid> Show IPC information of given task.",
  317.     .func = cmd_ipc_task,
  318.     .argc = 1,
  319.     .argv = &ipc_task_argv
  320. };
  321.  
  322. /* Data and methods for 'zone' command */
  323. static int cmd_zone(cmd_arg_t *argv);
  324. static cmd_arg_t zone_argv = {
  325.     .type = ARG_TYPE_INT,
  326. };
  327.  
  328. static cmd_info_t zone_info = {
  329.     .name = "zone",
  330.     .description = "Show memory zone structure.",
  331.     .func = cmd_zone,
  332.     .argc = 1,
  333.     .argv = &zone_argv
  334. };
  335.  
  336. /* Data and methods for 'cpus' command. */
  337. static int cmd_cpus(cmd_arg_t *argv);
  338. cmd_info_t cpus_info = {
  339.     .name = "cpus",
  340.     .description = "List all processors.",
  341.     .help = NULL,
  342.     .func = cmd_cpus,
  343.     .argc = 0,
  344.     .argv = NULL
  345. };
  346.  
  347. /* Data and methods for 'version' command. */
  348. static int cmd_version(cmd_arg_t *argv);
  349. cmd_info_t version_info = {
  350.     .name = "version",
  351.     .description = "Print version information.",
  352.     .help = NULL,
  353.     .func = cmd_version,
  354.     .argc = 0,
  355.     .argv = NULL
  356. };
  357.  
  358. static cmd_info_t *basic_commands[] = {
  359.     &call0_info,
  360.     &call1_info,
  361.     &call2_info,
  362.     &call3_info,
  363.     &continue_info,
  364.     &cpus_info,
  365.     &desc_info,
  366.     &exit_info,
  367.     &halt_info,
  368.     &help_info,
  369.     &ipc_task_info,
  370.     &set4_info,
  371.     &slabs_info,
  372.     &symaddr_info,
  373.     &sched_info,
  374.     &threads_info,
  375.     &tasks_info,
  376.     &tlb_info,
  377.     &version_info,
  378.     &zones_info,
  379.     &zone_info,
  380.     NULL
  381. };
  382.  
  383.  
  384. /** Initialize command info structure.
  385.  *
  386.  * @param cmd Command info structure.
  387.  *
  388.  */
  389. void cmd_initialize(cmd_info_t *cmd)
  390. {
  391.     spinlock_initialize(&cmd->lock, "cmd");
  392.     link_initialize(&cmd->link);
  393. }
  394.  
  395. /** Initialize and register commands. */
  396. void cmd_init(void)
  397. {
  398.     int i;
  399.  
  400.     for (i=0;basic_commands[i]; i++) {
  401.         cmd_initialize(basic_commands[i]);
  402.         if (!cmd_register(basic_commands[i]))
  403.             panic("could not register command %s\n",
  404.                   basic_commands[i]->name);
  405.     }
  406. }
  407.  
  408.  
  409. /** List supported commands.
  410.  *
  411.  * @param argv Argument vector.
  412.  *
  413.  * @return 0 on failure, 1 on success.
  414.  */
  415. int cmd_help(cmd_arg_t *argv)
  416. {
  417.     link_t *cur;
  418.  
  419.     spinlock_lock(&cmd_lock);
  420.    
  421.     for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
  422.         cmd_info_t *hlp;
  423.        
  424.         hlp = list_get_instance(cur, cmd_info_t, link);
  425.         spinlock_lock(&hlp->lock);
  426.        
  427.         printf("%s - %s\n", hlp->name, hlp->description);
  428.  
  429.         spinlock_unlock(&hlp->lock);
  430.     }
  431.    
  432.     spinlock_unlock(&cmd_lock);
  433.  
  434.     return 1;
  435. }
  436.  
  437. /** Describe specified command.
  438.  *
  439.  * @param argv Argument vector.
  440.  *
  441.  * @return 0 on failure, 1 on success.
  442.  */
  443. int cmd_desc(cmd_arg_t *argv)
  444. {
  445.     link_t *cur;
  446.  
  447.     spinlock_lock(&cmd_lock);
  448.    
  449.     for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
  450.         cmd_info_t *hlp;
  451.        
  452.         hlp = list_get_instance(cur, cmd_info_t, link);
  453.         spinlock_lock(&hlp->lock);
  454.  
  455.         if (strncmp(hlp->name, (const char *) argv->buffer, strlen(hlp->name)) == 0) {
  456.             printf("%s - %s\n", hlp->name, hlp->description);
  457.             if (hlp->help)
  458.                 hlp->help();
  459.             spinlock_unlock(&hlp->lock);
  460.             break;
  461.         }
  462.  
  463.         spinlock_unlock(&hlp->lock);
  464.     }
  465.    
  466.     spinlock_unlock(&cmd_lock);
  467.  
  468.     return 1;
  469. }
  470.  
  471. /** Search symbol table */
  472. int cmd_symaddr(cmd_arg_t *argv)
  473. {
  474.     symtab_print_search(argv->buffer);
  475.    
  476.     return 1;
  477. }
  478.  
  479. /** Call function with zero parameters */
  480. int cmd_call0(cmd_arg_t *argv)
  481. {
  482.     uintptr_t symaddr;
  483.     char *symbol;
  484.     unative_t (*f)(void);
  485. #ifdef ia64
  486.     struct {
  487.         unative_t f;
  488.         unative_t gp;
  489.     }fptr;
  490. #endif
  491.  
  492.     symaddr = get_symbol_addr(argv->buffer);
  493.     if (!symaddr)
  494.         printf("Symbol %s not found.\n", argv->buffer);
  495.     else if (symaddr == (uintptr_t) -1) {
  496.         symtab_print_search(argv->buffer);
  497.         printf("Duplicate symbol, be more specific.\n");
  498.     } else {
  499.         symbol = get_symtab_entry(symaddr);
  500.         printf("Calling f(): %.*p: %s\n", sizeof(uintptr_t) * 2, symaddr, symbol);
  501. #ifdef ia64
  502.         fptr.f = symaddr;
  503.         fptr.gp = ((unative_t *)cmd_call2)[1];
  504.         f =  (unative_t (*)(void)) &fptr;
  505. #else
  506.         f =  (unative_t (*)(void)) symaddr;
  507. #endif
  508.         printf("Result: %#zx\n", f());
  509.     }
  510.    
  511.     return 1;
  512. }
  513.  
  514. /** Call function with one parameter */
  515. int cmd_call1(cmd_arg_t *argv)
  516. {
  517.     uintptr_t symaddr;
  518.     char *symbol;
  519.     unative_t (*f)(unative_t,...);
  520.     unative_t arg1 = argv[1].intval;
  521. #ifdef ia64
  522.     struct {
  523.         unative_t f;
  524.         unative_t gp;
  525.     }fptr;
  526. #endif
  527.  
  528.     symaddr = get_symbol_addr(argv->buffer);
  529.     if (!symaddr)
  530.         printf("Symbol %s not found.\n", argv->buffer);
  531.     else if (symaddr == (uintptr_t) -1) {
  532.         symtab_print_search(argv->buffer);
  533.         printf("Duplicate symbol, be more specific.\n");
  534.     } else {
  535.         symbol = get_symtab_entry(symaddr);
  536.  
  537.         printf("Calling f(%#zx): %.*p: %s\n", arg1, sizeof(uintptr_t) * 2, symaddr, symbol);
  538. #ifdef ia64
  539.         fptr.f = symaddr;
  540.         fptr.gp = ((unative_t *)cmd_call2)[1];
  541.         f =  (unative_t (*)(unative_t,...)) &fptr;
  542. #else
  543.         f =  (unative_t (*)(unative_t,...)) symaddr;
  544. #endif
  545.         printf("Result: %#zx\n", f(arg1));
  546.     }
  547.    
  548.     return 1;
  549. }
  550.  
  551. /** Call function with two parameters */
  552. int cmd_call2(cmd_arg_t *argv)
  553. {
  554.     uintptr_t symaddr;
  555.     char *symbol;
  556.     unative_t (*f)(unative_t,unative_t,...);
  557.     unative_t arg1 = argv[1].intval;
  558.     unative_t arg2 = argv[2].intval;
  559. #ifdef ia64
  560.     struct {
  561.         unative_t f;
  562.         unative_t gp;
  563.     }fptr;
  564. #endif
  565.  
  566.     symaddr = get_symbol_addr(argv->buffer);
  567.     if (!symaddr)
  568.         printf("Symbol %s not found.\n", argv->buffer);
  569.     else if (symaddr == (uintptr_t) -1) {
  570.         symtab_print_search(argv->buffer);
  571.         printf("Duplicate symbol, be more specific.\n");
  572.     } else {
  573.         symbol = get_symtab_entry(symaddr);
  574.         printf("Calling f(0x%zx,0x%zx): %.*p: %s\n",
  575.                arg1, arg2, sizeof(uintptr_t) * 2, symaddr, symbol);
  576. #ifdef ia64
  577.         fptr.f = symaddr;
  578.         fptr.gp = ((unative_t *)cmd_call2)[1];
  579.         f =  (unative_t (*)(unative_t,unative_t,...)) &fptr;
  580. #else
  581.         f =  (unative_t (*)(unative_t,unative_t,...)) symaddr;
  582. #endif
  583.         printf("Result: %#zx\n", f(arg1, arg2));
  584.     }
  585.    
  586.     return 1;
  587. }
  588.  
  589. /** Call function with three parameters */
  590. int cmd_call3(cmd_arg_t *argv)
  591. {
  592.     uintptr_t symaddr;
  593.     char *symbol;
  594.     unative_t (*f)(unative_t,unative_t,unative_t,...);
  595.     unative_t arg1 = argv[1].intval;
  596.     unative_t arg2 = argv[2].intval;
  597.     unative_t arg3 = argv[3].intval;
  598. #ifdef ia64
  599.     struct {
  600.         unative_t f;
  601.         unative_t gp;
  602.     }fptr;
  603. #endif
  604.  
  605.     symaddr = get_symbol_addr(argv->buffer);
  606.     if (!symaddr)
  607.         printf("Symbol %s not found.\n", argv->buffer);
  608.     else if (symaddr == (uintptr_t) -1) {
  609.         symtab_print_search(argv->buffer);
  610.         printf("Duplicate symbol, be more specific.\n");
  611.     } else {
  612.         symbol = get_symtab_entry(symaddr);
  613.         printf("Calling f(0x%zx,0x%zx, 0x%zx): %.*p: %s\n",
  614.                arg1, arg2, arg3, sizeof(uintptr_t) * 2, symaddr, symbol);
  615. #ifdef ia64
  616.         fptr.f = symaddr;
  617.         fptr.gp = ((unative_t *)cmd_call2)[1];
  618.         f =  (unative_t (*)(unative_t,unative_t,unative_t,...)) &fptr;
  619. #else
  620.         f =  (unative_t (*)(unative_t,unative_t,unative_t,...)) symaddr;
  621. #endif
  622.         printf("Result: %#zx\n", f(arg1, arg2, arg3));
  623.     }
  624.    
  625.     return 1;
  626. }
  627.  
  628.  
  629. /** Print detailed description of 'describe' command. */
  630. void desc_help(void)
  631. {
  632.     printf("Syntax: describe command_name\n");
  633. }
  634.  
  635. /** Halt the kernel.
  636.  *
  637.  * @param argv Argument vector (ignored).
  638.  *
  639.  * @return 0 on failure, 1 on success (never returns).
  640.  */
  641. int cmd_halt(cmd_arg_t *argv)
  642. {
  643.     halt();
  644.     return 1;
  645. }
  646.  
  647. /** Command for printing TLB contents.
  648.  *
  649.  * @param argv Not used.
  650.  *
  651.  * @return Always returns 1.
  652.  */
  653. int cmd_tlb(cmd_arg_t *argv)
  654. {
  655.     tlb_print();
  656.     return 1;
  657. }
  658.  
  659. /** Write 4 byte value to address */
  660. int cmd_set4(cmd_arg_t *argv)
  661. {
  662.     uint32_t *addr ;
  663.     uint32_t arg1 = argv[1].intval;
  664.     bool pointer = false;
  665.  
  666.     if (((char *)argv->buffer)[0] == '*') {
  667.         addr = (uint32_t *) get_symbol_addr(argv->buffer+1);
  668.         pointer = true;
  669.     } else if (((char *)argv->buffer)[0] >= '0' &&
  670.            ((char *)argv->buffer)[0] <= '9')
  671.         addr = (uint32_t *)atoi((char *)argv->buffer);
  672.     else
  673.         addr = (uint32_t *)get_symbol_addr(argv->buffer);
  674.  
  675.     if (!addr)
  676.         printf("Symbol %s not found.\n", argv->buffer);
  677.     else if (addr == (uint32_t *) -1) {
  678.         symtab_print_search(argv->buffer);
  679.         printf("Duplicate symbol, be more specific.\n");
  680.     } else {
  681.         if (pointer)
  682.             addr = (uint32_t *)(*(unative_t *)addr);
  683.         printf("Writing 0x%x -> %.*p\n", arg1, sizeof(uintptr_t) * 2, addr);
  684.         *addr = arg1;
  685.        
  686.     }
  687.    
  688.     return 1;
  689. }
  690.  
  691. /** Command for listings SLAB caches
  692.  *
  693.  * @param argv Ignores
  694.  *
  695.  * @return Always 1
  696.  */
  697. int cmd_slabs(cmd_arg_t * argv) {
  698.     slab_print_list();
  699.     return 1;
  700. }
  701.  
  702.  
  703. /** Command for listings Thread information
  704.  *
  705.  * @param argv Ignores
  706.  *
  707.  * @return Always 1
  708.  */
  709. int cmd_threads(cmd_arg_t * argv) {
  710.     thread_print_list();
  711.     return 1;
  712. }
  713.  
  714. /** Command for listings Task information
  715.  *
  716.  * @param argv Ignores
  717.  *
  718.  * @return Always 1
  719.  */
  720. int cmd_tasks(cmd_arg_t * argv) {
  721.     task_print_list();
  722.     return 1;
  723. }
  724.  
  725. /** Command for listings Thread information
  726.  *
  727.  * @param argv Ignores
  728.  *
  729.  * @return Always 1
  730.  */
  731. int cmd_sched(cmd_arg_t * argv) {
  732.     sched_print_list();
  733.     return 1;
  734. }
  735.  
  736. /** Command for listing memory zones
  737.  *
  738.  * @param argv Ignored
  739.  *
  740.  * return Always 1
  741.  */
  742. int cmd_zones(cmd_arg_t * argv) {
  743.     zone_print_list();
  744.     return 1;
  745. }
  746.  
  747. /** Command for memory zone details
  748.  *
  749.  * @param argv Integer argument from cmdline expected
  750.  *
  751.  * return Always 1
  752.  */
  753. int cmd_zone(cmd_arg_t * argv) {
  754.     zone_print_one(argv[0].intval);
  755.     return 1;
  756. }
  757.  
  758. /** Command for printing task ipc details
  759.  *
  760.  * @param argv Integer argument from cmdline expected
  761.  *
  762.  * return Always 1
  763.  */
  764. int cmd_ipc_task(cmd_arg_t * argv) {
  765.     ipc_print_task(argv[0].intval);
  766.     return 1;
  767. }
  768.  
  769.  
  770. /** Command for listing processors.
  771.  *
  772.  * @param argv Ignored.
  773.  *
  774.  * return Always 1.
  775.  */
  776. int cmd_cpus(cmd_arg_t *argv)
  777. {
  778.     cpu_list();
  779.     return 1;
  780. }
  781.  
  782. /** Command for printing kernel version.
  783.  *
  784.  * @param argv Ignored.
  785.  *
  786.  * return Always 1.
  787.  */
  788. int cmd_version(cmd_arg_t *argv)
  789. {
  790.     version_print();
  791.     return 1;
  792. }
  793.  
  794. /** Command for returning console back to userspace.
  795.  *
  796.  * @param argv Ignored.
  797.  *
  798.  * return Always 1.
  799.  */
  800. int cmd_continue(cmd_arg_t *argv)
  801. {
  802.     printf("The kernel will now relinquish the console.\n");
  803.     printf("Use userspace controls to redraw the screen.\n");
  804.     arch_release_console();
  805.     /* TODO: send some vitual IRQ */
  806.     ipc_irq_send_msg(NULL, 0, 0, 0);
  807.     return 1;
  808. }
  809.  
  810. /** @}
  811.  */
  812.