X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=second%2Ffile.c;h=5d5ccbdf10bd2df10b687fb2d5ae867025a74772;hb=8e64db245a2d402dc89fa1f68a3789203815b238;hp=e5135995a74e33fb73ebec5e318b8baa71c5f033;hpb=98eacaa1983cde1532e80e67466dfa615e5564a2;p=tonyb-yaboot.git diff --git a/second/file.c b/second/file.c index e513599..5d5ccbd 100644 --- a/second/file.c +++ b/second/file.c @@ -38,6 +38,19 @@ extern char bootdevice[]; +/* Convert __u32 into std, dotted quad string, leaks like a sive :( */ +static char * +ipv4_to_str(__u32 ip) +{ + char *buf = malloc(sizeof("000.000.000.000")); + + sprintf(buf,"%u.%u.%u.%u", + (ip & 0xff000000) >> 24, (ip & 0x00ff0000) >> 16, + (ip & 0x0000ff00) >> 8, (ip & 0x000000ff)); + + return buf; +} + /* * Copy the string from source to dest till newline or comma(,) is seen * in the source. @@ -62,19 +75,14 @@ scopy(char **dest, char **source) } /* - * Extract all the arguments provided in the imagepath and fill it in result. + * Extract all the ipv4 arguments from the bootpath provided and fill result * Returns 1 on success, 0 on failure. */ static int -extract_args_from_netdev_path(char *imagepath, struct boot_fspec_t *result) +extract_ipv4_args(char *imagepath, struct boot_fspec_t *result) { char *tmp, *args, *str, *start; - DEBUG_F("imagepath = %s\n", imagepath); - - if (!imagepath) - return 1; - args = strrchr(imagepath, ':'); if (!args) return 1; @@ -133,6 +141,73 @@ extract_args_from_netdev_path(char *imagepath, struct boot_fspec_t *result) if (!result->addl_params) return 0; } + return 1; +} + +/* + * Check netinfo for ipv4 parameters and add them to the fspec iff the + * fspec has no existing value. + * + * Returns 1 on success, 0 on failure. + */ +static int +extract_netinfo_args(struct boot_fspec_t *result) +{ + struct bootp_packet *packet; + + /* Check to see if we can get the [scyg]iaddr fields from netinfo */ + packet = prom_get_netinfo(); + if (!packet) + return 0; + + DEBUG_F("We have a boot packet\n"); + DEBUG_F(" siaddr = <%x>\n", packet->siaddr); + DEBUG_F(" ciaddr = <%x>\n", packet->ciaddr); + DEBUG_F(" yiaddr = <%x>\n", packet->yiaddr); + DEBUG_F(" giaddr = <%x>\n", packet->giaddr); + + /* Try to fallback to yiaddr if ciaddr is empty. Broken? */ + if (packet->ciaddr == 0 && packet->yiaddr != 0) + packet->ciaddr = packet->yiaddr; + + if ((result->siaddr == NULL || *(result->siaddr) == NULL) + && packet->siaddr != 0) + result->siaddr = ipv4_to_str(packet->siaddr); + if ((result->ciaddr == NULL || *(result->ciaddr) == NULL) + && packet->ciaddr != 0) + result->ciaddr = ipv4_to_str(packet->ciaddr); + if ((result->giaddr == NULL || *(result->giaddr) == NULL) + && packet->giaddr != 0) + result->giaddr = ipv4_to_str(packet->giaddr); + + /* FIXME: Yck! if we /still/ do not have a gateway then "cheat" and use + * the server. This will be okay if the client and server are on + * the same IP network, if not then lets hope the server does ICMP + * redirections */ + if (result->giaddr == NULL) { + result->giaddr = ipv4_to_str(packet->siaddr); + DEBUG_F("Forcing giaddr to siaddr <%s>\n", result->giaddr); + } + + return 1; +} + +/* + * Extract all the arguments provided in the imagepath and fill it in result. + * Returns 1 on success, 0 on failure. + */ +static int +extract_netboot_args(char *imagepath, struct boot_fspec_t *result) +{ + int ret; + + DEBUG_F("imagepath = %s\n", imagepath); + + if (!imagepath) + return 1; + + ret = extract_ipv4_args(imagepath, result); + ret |= extract_netinfo_args(result); DEBUG_F("siaddr = <%s>\n", result->siaddr); DEBUG_F("file = <%s>\n", result->file); @@ -141,7 +216,8 @@ extract_args_from_netdev_path(char *imagepath, struct boot_fspec_t *result) DEBUG_F("bootp_retries = <%s>\n", result->bootp_retries); DEBUG_F("tftp_retries = <%s>\n", result->tftp_retries); DEBUG_F("addl_params = <%s>\n", result->addl_params); - return 1; + + return ret; } static char *netdev_path_to_dev(const char *path) @@ -280,10 +356,13 @@ parse_device_path(char *imagepath, char *defdevice, int defpart, if (device_kind == FILE_DEVICE_NET) { if (strchr(ipath, ':')) { - if (extract_args_from_netdev_path(ipath, result) == 0) + if (extract_netboot_args(ipath, result) == 0) return 0; - } else + } else { + /* If we didn't get a ':' then look only in netinfo */ + extract_netinfo_args(result); result->file = strdup(ipath); + } if (!defdev) result->dev = netdev_path_to_dev(ipath);