diff options
Diffstat (limited to 'vl-android.c')
-rw-r--r-- | vl-android.c | 362 |
1 files changed, 279 insertions, 83 deletions
diff --git a/vl-android.c b/vl-android.c index caef03d..1afc8d2 100644 --- a/vl-android.c +++ b/vl-android.c @@ -338,9 +338,6 @@ extern char* op_http_proxy; // Path to the file containing specific key character map. char* op_charmap_file = NULL; -/* Framebuffer dimensions, passed with -android-gui option. */ -char* android_op_gui = NULL; - /* Path to hardware initialization file passed with -android-hw option. */ char* android_op_hwini = NULL; @@ -509,42 +506,6 @@ static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data) #endif } -/* Parses -android-gui command line option, extracting width, height and bits - * per pixel parameters for the GUI console used in this session of the - * emulator. -android-gui option contains exactly three comma-separated positive - * integer numbers in strict order: width goes first, width goes next, and bits - * per pixel goes third. This routine verifies that format and return 0 if all - * three numbers were extracted, or -1 if string format was incorrect for that - * option. Note that this routine does not verify that extracted values are - * correct! - */ -static int -parse_androig_gui_option(const char* op, int* width, int* height, int* bpp) -{ - char val[128]; - - if (get_param_value(val, 128, "width", op)) { - *width = strtol(val, NULL, 0); - } else { - fprintf(stderr, "option -android-gui is missing width parameter\n"); - return -1; - } - if (get_param_value(val, 128, "height", op)) { - *height = strtol(val, NULL, 0); - } else { - fprintf(stderr, "option -android-gui is missing height parameter\n"); - return -1; - } - if (get_param_value(val, 128, "bpp", op)) { - *bpp = strtol(val, NULL, 0); - } else { - fprintf(stderr, "option -android-gui is missing bpp parameter\n"); - return -1; - } - - return 0; -} - /***********************************************************/ void hw_error(const char *fmt, ...) { @@ -3659,6 +3620,164 @@ append_param(char* param_str, const char* arg, int size) } } +/* Parses an integer + * Pararm: + * str String containing a number to be parsed. + * result Passes the parsed integer in this argument + * returns 0 if ok, -1 if failed + */ +int +parse_int(const char *str, int *result) +{ + char* r; + *result = strtol(str, &r, 0); + if (r == NULL || *r != '\0') + return -1; + + return 0; +} + + +/* parses a null-terminated string specifying a network port (e.g., "80") or + * port range (e.g., "[6666-7000]"). In case of a single port, lport and hport + * are the same. Returns 0 on success, -1 on error. */ + +int parse_port_range(const char *str, unsigned short *lport, + unsigned short *hport) { + + unsigned int low = 0, high = 0; + char *p, *arg = strdup(str); + + if ((*arg == '[') && ((p = strrchr(arg, ']')) != NULL)) { + p = arg + 1; /* skip '[' */ + low = atoi(strtok(p, "-")); + high = atoi(strtok(NULL, "-")); + if ((low > 0) && (high > 0) && (low < high) && (high < 65535)) { + *lport = low; + *hport = high; + } + } + else { + low = atoi(arg); + if ((0 < low) && (low < 65535)) { + *lport = low; + *hport = low; + } + } + free(arg); + if (low != 0) + return 0; + return -1; +} + +/* + * Implements the generic port forwarding option + */ +void +net_slirp_forward(const char *optarg) +{ + /* + * we expect the following format: + * dst_net:dst_mask:dst_port:redirect_ip:redirect_port OR + * dst_net:dst_mask:[dp_range_start-dp_range_end]:redirect_ip:redirect_port + */ + char *argument = strdup(optarg), *p = argument; + char *dst_net, *dst_mask, *dst_port; + char *redirect_ip, *redirect_port; + uint32_t dnet, dmask, rip; + unsigned short dlport, dhport, rport; + + + dst_net = strtok(p, ":"); + dst_mask = strtok(NULL, ":"); + dst_port = strtok(NULL, ":"); + redirect_ip = strtok(NULL, ":"); + redirect_port = strtok(NULL, ":"); + + if (dst_net == NULL || dst_mask == NULL || dst_port == NULL || + redirect_ip == NULL || redirect_port == NULL) { + fprintf(stderr, + "Invalid argument for -net-forward, we expect " + "dst_net:dst_mask:dst_port:redirect_ip:redirect_port or " + "dst_net:dst_mask:[dp_range_start-dp_range_end]" + ":redirect_ip:redirect_port: %s\n", + optarg); + exit(1); + } + + /* inet_strtoip converts dotted address to host byte order */ + if (inet_strtoip(dst_net, &dnet) == -1) { + fprintf(stderr, "Invalid destination IP net: %s\n", dst_net); + exit(1); + } + if (inet_strtoip(dst_mask, &dmask) == -1) { + fprintf(stderr, "Invalid destination IP mask: %s\n", dst_mask); + exit(1); + } + if (inet_strtoip(redirect_ip, &rip) == -1) { + fprintf(stderr, "Invalid redirect IP address: %s\n", redirect_ip); + exit(1); + } + + if (parse_port_range(dst_port, &dlport, &dhport) == -1) { + fprintf(stderr, "Invalid destination port or port range\n"); + exit(1); + } + + rport = atoi(redirect_port); + if (!rport) { + fprintf(stderr, "Invalid redirect port: %s\n", redirect_port); + exit(1); + } + + dnet &= dmask; + + slirp_add_net_forward(dnet, dmask, dlport, dhport, + rip, rport); + + free(argument); +} + + +/* Parses an -allow-tcp or -allow-udp argument and inserts a corresponding + * entry in the allows list */ +void +slirp_allow(const char *optarg, u_int8_t proto) +{ + /* + * we expect the following format: + * dst_ip:dst_port OR dst_ip:[dst_lport-dst_hport] + */ + char *argument = strdup(optarg), *p = argument; + char *dst_ip_str, *dst_port_str; + uint32_t dst_ip; + unsigned short dst_lport, dst_hport; + + dst_ip_str = strtok(p, ":"); + dst_port_str = strtok(NULL, ":"); + + if (dst_ip_str == NULL || dst_port_str == NULL) { + fprintf(stderr, + "Invalid argument %s for -allow. We expect " + "dst_ip:dst_port or dst_ip:[dst_lport-dst_hport]\n", + optarg); + exit(1); + } + + if (inet_strtoip(dst_ip_str, &dst_ip) == -1) { + fprintf(stderr, "Invalid destination IP address: %s\n", dst_ip_str); + exit(1); + } + if (parse_port_range(dst_port_str, &dst_lport, &dst_hport) == -1) { + fprintf(stderr, "Invalid destination port or port range\n"); + exit(1); + } + + slirp_add_allow(dst_ip, dst_lport, dst_hport, proto); + + free(argument); +} + int main(int argc, char **argv, char **envp) { const char *gdbstub_dev = NULL; @@ -3706,9 +3825,7 @@ int main(int argc, char **argv, char **envp) #endif CPUState *env; int show_vnc_port = 0; -#ifdef CONFIG_STANDALONE_CORE IniFile* hw_ini = NULL; -#endif // CONFIG_STANDALONE_CORE /* Container for the kernel initialization parameters collected in this * routine. */ char kernel_cmdline_append[1024]; @@ -4416,6 +4533,89 @@ int main(int argc, char **argv, char **envp) } } break; + + /* -------------------------------------------------------*/ + /* User mode network stack restrictions */ + case QEMU_OPTION_drop_udp: + slirp_drop_udp(); + break; + case QEMU_OPTION_drop_tcp: + slirp_drop_tcp(); + break; + case QEMU_OPTION_allow_tcp: + slirp_allow(optarg, IPPROTO_TCP); + break; + case QEMU_OPTION_allow_udp: + slirp_allow(optarg, IPPROTO_UDP); + break; + case QEMU_OPTION_drop_log: + { + FILE* drop_log_fd; + drop_log_fd = fopen(optarg, "w"); + + if (!drop_log_fd) { + fprintf(stderr, "Cannot open drop log: %s\n", optarg); + exit(1); + } + + slirp_drop_log_fd(drop_log_fd); + } + break; + + case QEMU_OPTION_dns_log: + { + FILE* dns_log_fd; + dns_log_fd = fopen(optarg, "wb"); + + if (dns_log_fd == NULL) { + fprintf(stderr, "Cannot open dns log: %s\n", optarg); + exit(1); + } + + slirp_dns_log_fd(dns_log_fd); + } + break; + + + case QEMU_OPTION_max_dns_conns: + { + int max_dns_conns = 0; + if (parse_int(optarg, &max_dns_conns)) { + fprintf(stderr, + "qemu: syntax: -max-dns-conns max_connections\n"); + exit(1); + } + if (max_dns_conns <= 0 || max_dns_conns == LONG_MAX) { + fprintf(stderr, + "Invalid arg for max dns connections: %s\n", + optarg); + exit(1); + } + slirp_set_max_dns_conns(max_dns_conns); + } + break; + + case QEMU_OPTION_net_forward: + net_slirp_forward(optarg); + break; + case QEMU_OPTION_net_forward_tcp2sink: + { + SockAddress saddr; + + if (parse_host_port(&saddr, optarg)) { + fprintf(stderr, + "Invalid ip/port %s for " + "-forward-dropped-tcp2sink. " + "We expect 'sink_ip:sink_port'\n", + optarg); + exit(1); + } + slirp_forward_dropped_tcp2sink(saddr.u.inet.address, + saddr.u.inet.port); + } + break; + /* -------------------------------------------------------*/ + case QEMU_OPTION_tb_size: tb_size = strtol(optarg, NULL, 0); if (tb_size < 0) @@ -4508,10 +4708,6 @@ int main(int argc, char **argv, char **envp) op_charmap_file = (char*)optarg; break; - case QEMU_OPTION_android_gui: - android_op_gui = (char*)optarg; - break; - case QEMU_OPTION_android_hw: android_op_hwini = (char*)optarg; break; @@ -4608,17 +4804,6 @@ int main(int argc, char **argv, char **envp) } } - /* Parse GUI option early, so when we init framebuffer in goldfish we have - * saved display parameters. */ - if (android_op_gui) { - if (parse_androig_gui_option(android_op_gui, - &android_display_width, - &android_display_height, - &android_display_bpp)) { - PANIC("Unable to parse -android-gui parameter: %s", android_op_gui); - } - } - /* Initialize character map. */ if (android_charmap_setup(op_charmap_file)) { if (op_charmap_file) { @@ -4641,20 +4826,33 @@ int main(int argc, char **argv, char **envp) data_dir = CONFIG_QEMU_SHAREDIR; } -#ifdef CONFIG_STANDALONE_CORE - /* Initialize hardware configuration. */ - if (android_op_hwini) { - hw_ini = iniFile_newFromFile(android_op_hwini); - if (hw_ini == NULL) { + if (!android_op_hwini) { + PANIC("Missing -android-hw <file> option!"); + } + hw_ini = iniFile_newFromFile(android_op_hwini); + if (hw_ini == NULL) { PANIC("Could not find %s file.", android_op_hwini); - } - } else { - hw_ini = iniFile_newFromMemory("", 0); } - androidHwConfig_read(android_hw, hw_ini); iniFile_free(hw_ini); -#endif // CONFIG_STANDALONE_CORE + + { + int width = android_hw->hw_lcd_width; + int height = android_hw->hw_lcd_height; + int depth = android_hw->hw_lcd_depth; + + /* A bit of sanity checking */ + if (width <= 0 || height <= 0 || + (depth != 16 && depth != 32) || + (((width|height) & 3) != 0) ) + { + PANIC("Invalid display configuration (%d,%d,%d)", + width, height, depth); + } + android_display_width = width; + android_display_height = height; + android_display_bpp = depth; + } #ifdef CONFIG_NAND_LIMITS /* Init nand stuff. */ @@ -4689,11 +4887,10 @@ int main(int argc, char **argv, char **envp) } /* Initialize LCD density */ - if (android_op_lcd_density) { - char* end; - long density = strtol(android_op_lcd_density, &end, 0); - if (end == NULL || *end || density < 0) { - PANIC("option -lcd-density must be a positive integer"); + if (android_hw->hw_lcd_density) { + long density = android_hw->hw_lcd_density; + if (density <= 0) { + PANIC("Invalid hw.lcd.density value: %ld", density); } hwLcd_setBootProperty(density); } @@ -4968,8 +5165,12 @@ int main(int argc, char **argv, char **envp) } /* init the memory */ - if (ram_size == 0) - ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; + if (ram_size == 0) { + ram_size = android_hw->hw_ramSize * 1024LL * 1024; + if (ram_size == 0) { + ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; + } + } #ifdef CONFIG_KQEMU /* FIXME: This is a nasty hack because kqemu can't cope with dynamic @@ -5199,16 +5400,11 @@ int main(int argc, char **argv, char **envp) /* just use the first displaystate for the moment */ ds = get_displaystate(); - if (android_op_gui) { - /* Initialize display from the command line parameters. */ - android_display_reset(ds, - android_display_width, - android_display_height, - android_display_bpp); - } else { - /* By default, use 320x480x16 */ - android_display_reset(ds, 320, 480, 16); - } + /* Initialize display from the command line parameters. */ + android_display_reset(ds, + android_display_width, + android_display_height, + android_display_bpp); if (display_type == DT_DEFAULT) { #if defined(CONFIG_SDL) || defined(CONFIG_COCOA) |