X-Git-Url: http://git.ozlabs.org/?p=yaboot.git;a=blobdiff_plain;f=util%2Faddnote.c;h=56de0c75e40058e6b665da8f9c9b68e13b813dd1;hp=90434c8c2a3a63259e115ee8bc82bb5f2e88d038;hb=a01ba048668c5a7e5efa2aa41eeb0a3ed374a63a;hpb=2ad0d7649e5042cad43a16b4a03bf53f39948316 diff --git a/util/addnote.c b/util/addnote.c index 90434c8..56de0c7 100644 --- a/util/addnote.c +++ b/util/addnote.c @@ -28,6 +28,7 @@ #include #include +/* CHRP note section */ char arch[] = "PowerPC"; #define N_DESCR 6 @@ -40,6 +41,29 @@ unsigned int descr[N_DESCR] = { 0x4000, /* load-base */ }; +/* RPA note section */ +char rpaname[] = "IBM,RPA-Client-Config"; + +/* + * Note: setting ignore_my_client_config *should* mean that OF ignores + * all the other fields, but there is a firmware bug which means that + * it looks at the splpar field at least. So these values need to be + * reasonable. + */ +#define N_RPA_DESCR 8 +unsigned int rpanote[N_RPA_DESCR] = { + 0, /* lparaffinity */ + 64, /* min_rmo_size */ + 0, /* min_rmo_percent */ + 40, /* max_pft_size */ + 1, /* splpar */ + -1, /* min_load */ + 0, /* new_mem_def */ + 1, /* ignore_my_client_config */ +}; + +#define ROUNDUP(len) (((len) + 3) & ~3) + unsigned char buf[512]; #define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1])) @@ -77,24 +101,25 @@ main(int ac, char **av) { int fd, n, i; int ph, ps, np; - int nnote, ns; + int nnote, nnote2, ns; if (ac != 2) { fprintf(stderr, "Usage: %s elf-file\n", av[0]); - exit(1); + return(1); } fd = open(av[1], O_RDWR); if (fd < 0) { perror(av[1]); - exit(1); + return(1); } - nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4; + nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr); + nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote); n = read(fd, buf, sizeof(buf)); if (n < 0) { perror("read"); - exit(1); + return(1); } if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0) @@ -104,7 +129,7 @@ main(int ac, char **av) || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) { fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n", av[1]); - exit(1); + return(1); } ph = GET_32BE(E_PHOFF); @@ -112,25 +137,25 @@ main(int ac, char **av) np = GET_16BE(E_PHNUM); if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) goto notelf; - if (ph + (np + 1) * ps + nnote > n) + if (ph + (np + 2) * ps + nnote + nnote2 > n) goto nospace; for (i = 0; i < np; ++i) { if (GET_32BE(ph + PH_TYPE) == PT_NOTE) { fprintf(stderr, "%s already has a note entry\n", av[1]); - exit(0); + return(0); } ph += ps; } /* XXX check that the area we want to use is all zeroes */ - for (i = 0; i < ps + nnote; ++i) + for (i = 0; i < 2 * ps + nnote + nnote2; ++i) if (buf[ph + i] != 0) goto nospace; /* fill in the program header entry */ - ns = ph + ps; + ns = ph + 2 * ps; PUT_32BE(ph + PH_TYPE, PT_NOTE); PUT_32BE(ph + PH_OFFSET, ns); PUT_32BE(ph + PH_FILESZ, nnote); @@ -142,37 +167,52 @@ main(int ac, char **av) PUT_32BE(ns + 8, 0x1275); strcpy(&buf[ns + 12], arch); ns += 12 + strlen(arch) + 1; - for (i = 0; i < N_DESCR; ++i) - PUT_32BE(ns + i * 4, descr[i]); + for (i = 0; i < N_DESCR; ++i, ns += 4) + PUT_32BE(ns, descr[i]); + + /* fill in the second program header entry and the RPA note area */ + ph += ps; + PUT_32BE(ph + PH_TYPE, PT_NOTE); + PUT_32BE(ph + PH_OFFSET, ns); + PUT_32BE(ph + PH_FILESZ, nnote2); + + /* fill in the note area we point to */ + PUT_32BE(ns, strlen(rpaname) + 1); + PUT_32BE(ns + 4, sizeof(rpanote)); + PUT_32BE(ns + 8, 0x12759999); + strcpy(&buf[ns + 12], rpaname); + ns += 12 + ROUNDUP(strlen(rpaname) + 1); + for (i = 0; i < N_RPA_DESCR; ++i, ns += 4) + PUT_32BE(ns, rpanote[i]); /* Update the number of program headers */ - PUT_16BE(E_PHNUM, np + 1); + PUT_16BE(E_PHNUM, np + 2); /* write back */ lseek(fd, (long) 0, SEEK_SET); i = write(fd, buf, n); if (i < 0) { perror("write"); - exit(1); + return(1); } if (i < n) { fprintf(stderr, "%s: write truncated\n", av[1]); - exit(1); + return(1); } - exit(0); + return(0); notelf: fprintf(stderr, "%s does not appear to be an ELF file\n", av[1]); - exit(1); + return(1); nospace: fprintf(stderr, "sorry, I can't find space in %s to put the note\n", av[1]); - exit(1); + return(1); } -/* +/* * Local variables: * c-file-style: "k&r" * c-basic-offset: 5