| /* |
| * QEMU monitor, target-dependent part |
| * |
| * Copyright (c) 2003-2004 Fabrice Bellard |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to deal |
| * in the Software without restriction, including without limitation the rights |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| * copies of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| * THE SOFTWARE. |
| */ |
| |
| #include "qemu/osdep.h" |
| #include "monitor-internal.h" |
| #include "monitor/qdev.h" |
| #include "net/slirp.h" |
| #include "sysemu/device_tree.h" |
| #include "monitor/hmp-target.h" |
| #include "monitor/hmp.h" |
| #include "block/block-hmp-cmds.h" |
| #include "qapi/qapi-commands-control.h" |
| #include "qapi/qapi-commands-misc.h" |
| #include "qapi/qapi-commands-machine.h" |
| #include "qapi/error.h" |
| #include "qemu/cutils.h" |
| |
| #if defined(TARGET_S390X) |
| #include "hw/s390x/storage-keys.h" |
| #include "hw/s390x/storage-attributes.h" |
| #endif |
| |
| /* Make devices configuration available for use in hmp-commands*.hx templates */ |
| #include CONFIG_DEVICES |
| |
| static HMPCommand hmp_info_cmds[]; |
| |
| /** |
| * Is @name in the '|' separated list of names @list? |
| */ |
| int hmp_compare_cmd(const char *name, const char *list) |
| { |
| const char *p, *pstart; |
| int len; |
| len = strlen(name); |
| p = list; |
| for (;;) { |
| pstart = p; |
| p = qemu_strchrnul(p, '|'); |
| if ((p - pstart) == len && !memcmp(pstart, name, len)) { |
| return 1; |
| } |
| if (*p == '\0') { |
| break; |
| } |
| p++; |
| } |
| return 0; |
| } |
| |
| /* Please update hmp-commands.hx when adding or changing commands */ |
| static HMPCommand hmp_info_cmds[] = { |
| #include "hmp-commands-info.h" |
| { NULL, NULL, }, |
| }; |
| |
| /* hmp_cmds and hmp_info_cmds would be sorted at runtime */ |
| HMPCommand hmp_cmds[] = { |
| #include "hmp-commands.h" |
| { NULL, NULL, }, |
| }; |
| |
| /* |
| * Set @pval to the value in the register identified by @name. |
| * return 0 if OK, -1 if not found |
| */ |
| int get_monitor_def(Monitor *mon, int64_t *pval, const char *name) |
| { |
| const MonitorDef *md = target_monitor_defs(); |
| CPUState *cs = mon_get_cpu(mon); |
| void *ptr; |
| uint64_t tmp = 0; |
| int ret; |
| |
| if (cs == NULL || md == NULL) { |
| return -1; |
| } |
| |
| for(; md->name != NULL; md++) { |
| if (hmp_compare_cmd(name, md->name)) { |
| if (md->get_value) { |
| *pval = md->get_value(mon, md, md->offset); |
| } else { |
| CPUArchState *env = mon_get_cpu_env(mon); |
| ptr = (uint8_t *)env + md->offset; |
| switch(md->type) { |
| case MD_I32: |
| *pval = *(int32_t *)ptr; |
| break; |
| case MD_TLONG: |
| *pval = *(target_long *)ptr; |
| break; |
| default: |
| *pval = 0; |
| break; |
| } |
| } |
| return 0; |
| } |
| } |
| |
| ret = target_get_monitor_def(cs, name, &tmp); |
| if (!ret) { |
| *pval = (target_long) tmp; |
| } |
| |
| return ret; |
| } |
| |
| static int |
| compare_mon_cmd(const void *a, const void *b) |
| { |
| return strcmp(((const HMPCommand *)a)->name, |
| ((const HMPCommand *)b)->name); |
| } |
| |
| static void __attribute__((__constructor__)) sortcmdlist(void) |
| { |
| qsort(hmp_cmds, ARRAY_SIZE(hmp_cmds) - 1, |
| sizeof(*hmp_cmds), |
| compare_mon_cmd); |
| qsort(hmp_info_cmds, ARRAY_SIZE(hmp_info_cmds) - 1, |
| sizeof(*hmp_info_cmds), |
| compare_mon_cmd); |
| } |
| |
| void monitor_register_hmp(const char *name, bool info, |
| void (*cmd)(Monitor *mon, const QDict *qdict)) |
| { |
| HMPCommand *table = info ? hmp_info_cmds : hmp_cmds; |
| |
| while (table->name != NULL) { |
| if (strcmp(table->name, name) == 0) { |
| g_assert(table->cmd == NULL && table->cmd_info_hrt == NULL); |
| table->cmd = cmd; |
| return; |
| } |
| table++; |
| } |
| g_assert_not_reached(); |
| } |
| |
| void monitor_register_hmp_info_hrt(const char *name, |
| HumanReadableText *(*handler)(Error **errp)) |
| { |
| HMPCommand *table = hmp_info_cmds; |
| |
| while (table->name != NULL) { |
| if (strcmp(table->name, name) == 0) { |
| g_assert(table->cmd == NULL && table->cmd_info_hrt == NULL); |
| table->cmd_info_hrt = handler; |
| return; |
| } |
| table++; |
| } |
| g_assert_not_reached(); |
| } |