diff -urN yaboot-1.3.14/include/prom.h yaboot-1.3.14-fixes/include/prom.h --- yaboot-1.3.14/include/prom.h 2007-08-17 10:29:26.000000000 -0400 +++ yaboot-1.3.14-fixes/include/prom.h 2008-05-05 13:40:11.000000000 -0400 @@ -37,6 +37,9 @@ #define PROM_INVALID_HANDLE ((prom_handle)-1UL) #define BOOTDEVSZ (2048) /* iscsi args can be in excess of 1040 bytes */ #define TOK_ISCSI "iscsi" +#define PROM_CLAIM_MAX_ADDR 0x8000000 +#define BOOTLASTSZ 1024 +#define FW_NBR_REBOOTSZ 4 struct prom_args; typedef int (*prom_entry)(struct prom_args *); @@ -85,6 +88,7 @@ /* memory */ +void *prom_claim_chunk(void *virt, unsigned int size, unsigned int align); void *prom_claim (void *virt, unsigned int size, unsigned int align); void prom_release(void *virt, unsigned int size); void prom_map (void *phys, void *virt, int size); @@ -154,5 +158,8 @@ struct bootp_packet * prom_get_netinfo (void); char * prom_get_mac (struct bootp_packet * packet); char * prom_get_ip (struct bootp_packet * packet); +char * prom_get_yiaddr (struct bootp_packet * packet); +char * prom_get_siaddr (struct bootp_packet * packet); +char * prom_get_giaddr (struct bootp_packet * packet); #endif diff -urN yaboot-1.3.14/second/fs_of.c yaboot-1.3.14-fixes/second/fs_of.c --- yaboot-1.3.14/second/fs_of.c 2007-08-17 10:29:26.000000000 -0400 +++ yaboot-1.3.14-fixes/second/fs_of.c 2008-05-05 13:41:53.000000000 -0400 @@ -44,9 +44,8 @@ #include "errors.h" #include "debug.h" -#define LOAD_BUFFER_POS 0x600000 -/* this cannot be safely increased any further */ -#define LOAD_BUFFER_SIZE 0x600000 +#define LOAD_BUFFER_POS 0x1000000 +#define LOAD_BUFFER_SIZE 0x1000000 static int of_open(struct boot_file_t* file, const char* dev_name, struct partition_t* part, const char* file_name); @@ -60,6 +59,8 @@ static int of_net_read(struct boot_file_t* file, unsigned int size, void* buffer); static int of_net_seek(struct boot_file_t* file, unsigned int newpos); +static int of_supports_real_tftp(void); +static int of_net_use_tftp = -1; struct fs_t of_filesystem = { @@ -131,6 +132,34 @@ return FILE_ERR_OK; } +/* + * older firmwares were really not capable of doing a tftp load. Ie, the + * 'boot' command line: :,, requires that + * to be running a bootp server, not simply a tftp server. The + * above syntax works with new firmwares. + * + * This function should return 1 if the running firmware fully supports + * tftp and 0 if not. + */ +static int of_supports_real_tftp() { + of_net_use_tftp=1; + return(of_net_use_tftp); +/* + prom_handle h; + if(of_net_use_tftp>=0) return(of_net_use_tftp); + + h=prom_open("/packages/cas"); + if(h) { + prom_close(h); + of_net_use_tftp=1; + } else { + of_net_use_tftp=0; + } + return(of_net_use_tftp); +*/ +} + + static int of_net_open(struct boot_file_t* file, const char* dev_name, struct partition_t* part, const char* file_name) @@ -138,18 +167,34 @@ static char buffer[1024]; char *filename; char *p; + struct bootp_packet *packet; DEBUG_ENTER; DEBUG_OPEN; + strncpy(buffer, dev_name, 768); if (file_name && strlen(file_name)) { + if(of_supports_real_tftp()){ + packet = prom_get_netinfo(); + strcat(buffer, prom_get_siaddr(packet)); + } strcat(buffer, ","); filename = strdup(file_name); for (p = filename; *p; p++) if (*p == '/') *p = '\\'; strcat(buffer, filename); + if(of_supports_real_tftp()) { + strcat(buffer, ","); + strcat(buffer, prom_get_yiaddr(packet)); + strcat(buffer, ","); + /* Hack required since giaddr not returned on some systems + and required to boot on those systems. This should work + for the client and server on the same subnet. */ + strcat(buffer, prom_get_siaddr(packet)); + } + strcat(buffer,",,100"); free(filename); } @@ -166,7 +211,9 @@ return FILE_ERR_BAD_FSYS; } - file->buffer = prom_claim((void *)LOAD_BUFFER_POS, LOAD_BUFFER_SIZE, 0); + + file->buffer = prom_claim_chunk((void *)LOAD_BUFFER_POS, + LOAD_BUFFER_SIZE, 0); if (file->buffer == (void *)-1) { prom_printf("Can't claim memory for TFTP download\n"); prom_close(file->of_device); diff -urN yaboot-1.3.14/second/prom.c yaboot-1.3.14-fixes/second/prom.c --- yaboot-1.3.14/second/prom.c 2007-08-17 10:29:26.000000000 -0400 +++ yaboot-1.3.14-fixes/second/prom.c 2008-05-05 13:40:11.000000000 -0400 @@ -568,6 +568,25 @@ while (prom_getms() <= end); } +/* if address given is claimed look for other addresses to get the needed + * space before giving up + */ +void * +prom_claim_chunk(void *virt, unsigned int size, unsigned int align) +{ + void *found, *addr; + for(addr=virt; addr <= (void*)PROM_CLAIM_MAX_ADDR; + addr+=(0x100000/sizeof(addr))) { + found = prom_claim(addr, size, 0); + if (found != (void *)-1) { + DEBUG_F("claimed %i at 0x%x (0x%x)\n",size,(int)found,(int)virt); + return(found); + } + } + prom_printf("Claim error, can't allocate %x at 0x%x\n",size,(int)virt); + return((void*)-1); +} + void * prom_claim (void *virt, unsigned int size, unsigned int align) { @@ -752,6 +771,78 @@ } /* + * prom_get_yiaddr() + * returns the ip addr of the client in dotted decimal format + */ +char * prom_get_yiaddr (struct bootp_packet * packet) +{ + char * conf_path; + + if (!packet) + return NULL; + + /* 15 chars in yiaddr + \0 */ + conf_path = malloc(16); + if (!conf_path) + return NULL; + sprintf(conf_path, "%d.%d.%d.%d", + packet->yiaddr >> 24, + (packet->yiaddr << 8) >> 24, + (packet->yiaddr << 16) >> 24, + (packet->yiaddr << 24) >> 24); + + return conf_path; +} + +/* + * prom_get_siaddr() + * returns the ip addr of the server in dotted decimal format + */ +char * prom_get_siaddr (struct bootp_packet * packet) +{ + char * conf_path; + + if (!packet) + return NULL; + + /* 15 chars in siaddr + \0 */ + conf_path = malloc(16); + if (!conf_path) + return NULL; + sprintf(conf_path, "%d.%d.%d.%d", + packet->siaddr >> 24, + (packet->siaddr << 8) >> 24, + (packet->siaddr << 16) >> 24, + (packet->siaddr << 24) >> 24); + + return conf_path; +} + +/* + * prom_get_giaddr() + * returns the ip addr of the gateway in dotted decimal format + */ +char * prom_get_giaddr (struct bootp_packet * packet) +{ + char * conf_path; + + if (!packet) + return NULL; + + /* 15 chars in giaddr + \0 */ + conf_path = malloc(16); + if (!conf_path) + return NULL; + sprintf(conf_path, "%d.%d.%d.%d", + packet->giaddr >> 24, + (packet->giaddr << 8) >> 24, + (packet->giaddr << 16) >> 24, + (packet->giaddr << 24) >> 24); + + return conf_path; +} + +/* * Local variables: * c-file-style: "k&r" * c-basic-offset: 5 diff -urN yaboot-1.3.14/second/yaboot.c yaboot-1.3.14-fixes/second/yaboot.c --- yaboot-1.3.14/second/yaboot.c 2007-08-17 10:29:26.000000000 -0400 +++ yaboot-1.3.14-fixes/second/yaboot.c 2008-05-05 13:43:48.000000000 -0400 @@ -114,6 +114,9 @@ char bootdevice[BOOTDEVSZ]; char bootoncelabel[1024]; char bootargs[1024]; +char bootlastlabel[BOOTLASTSZ] = {0}; +char fw_nbr_reboots[FW_NBR_REBOOTSZ] = {0}; +long fw_reboot_cnt = 0; char *password = NULL; struct boot_fspec_t boot; int _machine = _MACH_Pmac; @@ -471,12 +474,13 @@ if (!fspec.file) goto out; - sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype); + /* sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype); strcat(fspec.file, prom_get_mac(packet)); rc = load_config_file(&fspec); if (rc) goto out; + */ /* * Now try to match on IP. @@ -665,7 +669,7 @@ cmdinit(); - if (first) { + if (first && !fw_reboot_cnt) { first = 0; imagename = bootargs; word_split(&imagename, ¶ms->args); @@ -680,6 +684,13 @@ timeout = simple_strtol(q, NULL, 0); } + /* If this is a reboot due to FW detecting CAS changes then + * set timeout to 1. The last kernel booted will be booted + * again automatically. It should seem seamless to the user + */ + if (fw_reboot_cnt) + timeout = 1; + prom_printf("boot: "); c = -1; if (timeout != -1) { @@ -716,7 +727,9 @@ if (!imagename) { if (bootoncelabel[0] != 0) imagename = bootoncelabel; - else + else if (bootlastlabel[0] != 0) + imagename = bootlastlabel; + else imagename = cfg_get_default(); } if (imagename) @@ -737,6 +750,9 @@ if ( useconf && (!imagename || imagename[0] == 0 )) imagename = cfg_get_default(); + /* write the imagename out so it can be reused on reboot if necessary */ + prom_set_options("boot-last-label", imagename, strlen(imagename)); + label = 0; defdevice = boot.dev; @@ -1233,7 +1249,7 @@ Elf32_Ehdr *e = &(loadinfo->elf.elf32hdr); Elf32_Phdr *p, *ph; int size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident); - unsigned long addr, loadaddr; + unsigned long loadaddr; /* Read the rest of the Elf header... */ if ((*(file->fs->read))(file, size, &e->e_version) < size) { @@ -1321,13 +1337,7 @@ loadaddr = loadinfo->load_loc; } - /* On some systems, loadaddr may already be claimed, so try some - * other nearby addresses before giving up. - */ - for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) { - loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0); - if (loadinfo->base != (void *)-1) break; - } + loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0); if (loadinfo->base == (void *)-1) { prom_printf("Claim error, can't allocate kernel memory\n"); goto bail; @@ -1377,7 +1387,7 @@ Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr); Elf64_Phdr *p, *ph; int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident); - unsigned long addr, loadaddr; + unsigned long loadaddr; /* Read the rest of the Elf header... */ if ((*(file->fs->read))(file, size, &e->e_version) < size) { @@ -1465,13 +1475,7 @@ loadaddr = e->e_entry; } - /* On some systems, loadaddr may already be claimed, so try some - * other nearby addresses before giving up. - */ - for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) { - loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0); - if (loadinfo->base != (void *)-1) break; - } + loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0); if (loadinfo->base == (void *)-1) { prom_printf("Claim error, can't allocate kernel memory\n"); goto bail; @@ -1625,8 +1629,10 @@ yaboot_main(void) { char *ptype; + char *endp; int conf_given = 0; char conf_path[1024]; + int ret; if (_machine == _MACH_Pmac) setup_display(); @@ -1635,6 +1641,11 @@ DEBUG_F("/chosen/bootargs = %s\n", bootargs); prom_get_chosen("bootpath", bootdevice, BOOTDEVSZ); DEBUG_F("/chosen/bootpath = %s\n", bootdevice); + if (prom_get_options("ibm,#reconfig-reboots",fw_nbr_reboots, FW_NBR_REBOOTSZ) == -1 ) + prom_get_options("ibm,fw-nbr-reboots",fw_nbr_reboots, FW_NBR_REBOOTSZ); + fw_reboot_cnt = simple_strtol(fw_nbr_reboots,&endp,10); + if (fw_reboot_cnt > 0L) + prom_get_options("boot-last-label", bootlastlabel, BOOTLASTSZ); /* If conf= specified on command line, it overrides Usage: conf=device:partition,/path/to/conffile