aboutsummaryrefslogtreecommitdiffstats
path: root/vl-android.c
diff options
context:
space:
mode:
Diffstat (limited to 'vl-android.c')
-rw-r--r--vl-android.c362
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)