* [RFC] post-processing tool
@ 2004-10-04 3:40 Hollis Blanchard
2004-10-04 11:45 ` Marco Gerards
0 siblings, 1 reply; 3+ messages in thread
From: Hollis Blanchard @ 2004-10-04 3:40 UTC (permalink / raw)
To: grub-devel
The CHRP binding for IEEE 1275 says that ELF files loaded by firmware must
have a special PT_NOTE segment (segment, not section). [Aside: if Apple
firmware ever sees this NOTE, it renders itself unbootable.]
objcopy doesn't do segments, only sections. A linker script *could* do
what we need, but in order to use the PHDRS statement, it seems we would
need to write an entire linker script (which I would rather not do).
Linux uses a post-processing tool called addnote to add the NOTE segment
to a normal ELF file. I have written my own version of that, which I'm
calling "appendnote" to avoid confusion. If it goes into GRUB, it probably
belongs in a util/powerpc/ieee1275 directory.
I don't believe there exists a grub-setup for PPC, but this could warrant
it. One could run grub-setup on the target machine, which could be a shell
script that does the following:
- if the system is Old World Mac, install stage1 with a block list for
grubof
- if CHRP, run appendnote on grubof
- if CHRP or New World:
- find the OF device path to grubof (like ybin or SUSE's "lilo" script)
- use nvsetenv to point firmware to grubof
In that model, appendnote would be a tool compiled and installed on the
target. The alternative is to create grubof and grubof.chrp at compile
time, install both on the target, and let grub-setup point OF at one or
the other.
Any comments? How do I add this tool to the Makefiles?
-Hollis
/* appendnote.c -- add an IEEE 1275 CHRP NOTE segment to an ELF file. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <grub/elf.h>
#define ALIGN_UP(addr, align) ((long)((char *)addr + align - 1) & ~(align - 1))
struct chrp_note {
Elf32_Nhdr header;
unsigned char name[8];
uint32_t real_mode;
uint32_t real_base;
uint32_t real_size;
uint32_t virt_base;
uint32_t virt_size;
uint32_t load_base;
};
off_t segtable_size(void *file)
{
Elf32_Ehdr *elf_header = (Elf32_Ehdr *)file;
return elf_header->e_phentsize * elf_header->e_phnum;
}
int modify_elf(void *infile, off_t infile_size, void *outfile)
{
Elf32_Ehdr *orig_elf_header = (Elf32_Ehdr *)infile;
Elf32_Ehdr *new_elf_header = (Elf32_Ehdr *)outfile;
Elf32_Phdr *note_pheader;
struct chrp_note *note;
char arch[] = "PowerPC";
/* copy whole file */
memcpy(outfile, infile, infile_size);
/* copy the old segment table to the end of the file */
memcpy((uint8_t *)outfile + infile_size,
(uint8_t *)infile + orig_elf_header->e_phoff,
segtable_size(infile));
new_elf_header->e_phoff = infile_size;
/* calculate NOTE program header location */
note_pheader = (Elf32_Phdr *)((uint8_t *)outfile + infile_size);
note_pheader += new_elf_header->e_phnum; /* skip existing headers */
new_elf_header->e_phnum++; /* and now there is one more */
memset(note_pheader, 0, new_elf_header->e_phentsize);
note_pheader->p_type = PT_NOTE;
note_pheader->p_offset = new_elf_header->e_phoff + segtable_size(outfile);
note_pheader->p_filesz = sizeof(struct chrp_note);
/* now add the NOTE data */
note = (struct chrp_note *)(note_pheader + 1);
note->header.n_namesz = strlen(arch) + 1;
note->header.n_descsz = sizeof(struct chrp_note);
note->header.n_type = 0x1275;
strcpy(note->name, arch);
note->real_mode = 0xffffffff;
note->real_base = 0x00c00000;
note->real_size = 0xffffffff;
note->virt_base = 0xffffffff;
note->virt_size = 0xffffffff;
note->load_base = 0x00004000;
return 0;
}
int append_size(void *infile)
{
Elf32_Ehdr *elf_header = (Elf32_Ehdr *)infile;
return elf_header->e_phentsize * (elf_header->e_phnum + 1)
+ sizeof(struct chrp_note);
}
int is_elf (void *file)
{
Elf32_Ehdr *elf_header = (Elf32_Ehdr *)file;
if (memcmp (elf_header->e_ident, ELFMAG, SELFMAG))
return 0;
return 1;
}
void *open_infile(char *path, off_t size)
{
void *file;
int fd;
fd = open(path, O_RDONLY);
if (fd == -1) {
perror("open");
return NULL;
}
file = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
if (file == MAP_FAILED) {
perror("mmap");
return NULL;
}
return file;
}
void *open_outfile(char *path, off_t size)
{
void *file;
int fd;
fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd == -1) {
perror("open");
return NULL;
}
if (ftruncate(fd, size) == -1) {
perror("ftruncate");
return NULL;
}
file = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (file == MAP_FAILED) {
perror("mmap");
return NULL;
}
return file;
}
int main (int argc, char *argv[])
{
struct stat instat;
void *infile;
void *outfile;
off_t aligned_size;
if (argc < 3) {
fprintf (stderr, "Usage: %s <ELF file> <new ELF file>\n", argv[0]);
return 1;
}
if (stat(argv[1], &instat) == -1) {
perror("stat");
return 1;
}
aligned_size = ALIGN_UP(instat.st_size, 4);
infile = open_infile(argv[1], aligned_size);
if (infile == NULL) {
fprintf (stderr, "Couldn't open %s\n", argv[1]);
return 1;
}
outfile = open_outfile(argv[2], aligned_size + append_size(infile));
if (outfile == NULL) {
fprintf (stderr, "Couldn't open %s\n", argv[2]);
return 1;
}
if (!is_elf(infile)) {
fprintf (stderr, "%s: not an ELF file\n", argv[1]);
return 1;
}
modify_elf(infile, aligned_size, outfile);
return 0;
}
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [RFC] post-processing tool
2004-10-04 3:40 [RFC] post-processing tool Hollis Blanchard
@ 2004-10-04 11:45 ` Marco Gerards
2004-10-06 8:47 ` Yoshinori K. Okuji
0 siblings, 1 reply; 3+ messages in thread
From: Marco Gerards @ 2004-10-04 11:45 UTC (permalink / raw)
To: The development of GRUB 2
Hollis Blanchard <hollis@penguinppc.org> writes:
> Linux uses a post-processing tool called addnote to add the NOTE segment
> to a normal ELF file. I have written my own version of that, which I'm
> calling "appendnote" to avoid confusion. If it goes into GRUB, it probably
> belongs in a util/powerpc/ieee1275 directory.
This sounds sane to me.
> I don't believe there exists a grub-setup for PPC, but this could warrant
> it. One could run grub-setup on the target machine, which could be a shell
> script that does the following:
>
> - if the system is Old World Mac, install stage1 with a block list for
> grubof
> - if CHRP, run appendnote on grubof
> - if CHRP or New World:
> - find the OF device path to grubof (like ybin or SUSE's "lilo" script)
> - use nvsetenv to point firmware to grubof
Doesn't ybin mount the boot partition and copy yaboot there? I think
we have to do the same.
> In that model, appendnote would be a tool compiled and installed on the
> target. The alternative is to create grubof and grubof.chrp at compile
> time, install both on the target, and let grub-setup point OF at one or
> the other.
Both are fine for me. But the advantage of having grubof and
grubof.chrp is that distributions just need one package for multiple
platforms.
> Any comments? How do I add this tool to the Makefiles?
Add it to sbin_UTILITIES. BTW, I think grubof does not belong there,
but there is not a better place yet. When module loading is
implemented on the PPC, I will work on powerpc-ieee1275.rmk to make it
a bit more like the PC version.
Perhaps it would be nice if this utility checks if the ELF is a
powerpc ELF.
> struct chrp_note {
> Elf32_Nhdr header;
> unsigned char name[8];
> uint32_t real_mode;
> uint32_t real_base;
> uint32_t real_size;
> uint32_t virt_base;
> uint32_t virt_size;
> uint32_t load_base;
> };
Can you please revise this so the GCS is followed. In the GCS tabs
are not used, but instead of that two spaces. Also braces are on
their own lines. So this code will look like:
struct chrp_note
{
Elf32_Nhdr header;
unsigned char name[8];
uint32_t real_mode;
uint32_t real_base;
uint32_t real_size;
uint32_t virt_base;
uint32_t virt_size;
uint32_t load_base;
};
> off_t segtable_size(void *file)
Please put the return type on a separate line. Add a space after the
function name.
> return elf_header->e_phentsize * elf_header->e_phnum;
In case of a pointer, don't add a space after the star.
> if (argc < 3) {
> fprintf (stderr, "Usage: %s <ELF file> <new ELF file>\n", argv[0]);
> return 1;
> }
Is it possible to use a parser? I prefer argp, but we need to agree
what to use for utilities? This is also in the GCS to keep the GNU
utilities consistent. For example the help output should be
consistent with other utilities and --help should be accepted. When
using such parser we get all that for free. :)
I could do that if you want, I am used to argp and can implement such
thing in a few minutes.
Can you please modify the program so it is GCS compliant? For me it
is important to have a consistent coding style in GRUB. It is not a
problem for me to change all this, but it is a lot of work for me so I
prefer not to do this for every patch. :)
Thanks,
Marco
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [RFC] post-processing tool
2004-10-04 11:45 ` Marco Gerards
@ 2004-10-06 8:47 ` Yoshinori K. Okuji
0 siblings, 0 replies; 3+ messages in thread
From: Yoshinori K. Okuji @ 2004-10-06 8:47 UTC (permalink / raw)
To: The development of GRUB 2
On Monday 04 October 2004 13:45, Marco Gerards wrote:
> > In that model, appendnote would be a tool compiled and installed on
> > the target. The alternative is to create grubof and grubof.chrp at
> > compile time, install both on the target, and let grub-setup point
> > OF at one or the other.
>
> Both are fine for me. But the advantage of having grubof and
> grubof.chrp is that distributions just need one package for multiple
> platforms.
Basically the build process of GRUB should provide as many variants as
possible. Note that some users want to install GRUB for a different
platform, like installing GRUB into a CHRP machine on iMac.
Okuji
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2004-10-06 8:54 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-10-04 3:40 [RFC] post-processing tool Hollis Blanchard
2004-10-04 11:45 ` Marco Gerards
2004-10-06 8:47 ` Yoshinori K. Okuji
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.