Subject: Re: booting with floppy
To: None <heinz@netbsd.org>
From: Kazuki Sakamoto <sakamoto@splhack.org>
List: port-bebox
Date: 01/23/2001 10:25:12
heinz@netbsd.org wrote:

 >   Boot: Loading in()
 >   1580436+1528 [94+85072+71240]=0x1a88e8
 >   start=0x3100
 > 
 >   panic: uvm_setpagesize: page size not a power of two
 >   Stopped in iaslotcf_locnames at   0x12ade8:     lwz r0, r1, 0x14,
 >   db> 
 >
 > But why would the page size not be a power of two? I hope, this
 > is not a bug of the cross compiler...

-current kernel of bebox may be bad...

Please try to use the following filter to fix length of bss section.
I think "1528" is too short.

sakamoto
--
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/exec_elf.h>
#include <machine/endian.h>

#if BYTE_ORDER == LITTLE_ENDIAN
unsigned long
_BE_long(val)
	unsigned long val;
{
	unsigned char *p = (unsigned char *)&val;
	return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0));
}

unsigned short
_BE_short(val)
	unsigned short val;
{
	unsigned char *p = (unsigned char *)&val;
	return ((p[0] << 8) | (p[1] << 0));
}
#else
#define _BE_long(x) (x)
#define _BE_short(x) (x)
#endif

int
main(argc, argv)
	int argc;
	char *argv[];
{
	int i;
	int in_fd, out_fd;
	int bss_end = 0, sbss_end = 0;
	int p_memsz, p_memsz_offset;
	char *in_data;
	char *symtab;
	struct stat buf;
	Elf32_Ehdr *hdr;
	Elf32_Phdr *phdr;
	Elf32_Shdr *shdr;

	switch (argc) {
	case 3:
		if (stat(argv[1], &buf)) {
			perror("stat");
			exit(1);
		}
		if ((in_fd = open(argv[1], O_RDONLY)) < 0) {
			fprintf(stderr, "Can't open '%s': %s\n",
				argv[1], strerror(errno));
			exit(2);
		}
		if ((in_data = (char *)mmap(NULL, buf.st_size, PROT_READ,
		    MAP_PRIVATE, in_fd, 0)) == MAP_FAILED) {
			perror("mmap");
			exit(1); 
		}

		if ((out_fd = open(argv[2], O_WRONLY|O_CREAT, 0644)) < 0) {
			fprintf(stderr, "Can't open '%s': %s\n",
				argv[2], strerror(errno));
			exit(2);
		}
		break;

	default:
		fprintf(stderr, "usage: %s IN OUT\n", argv[0]);
		exit(1);
	}

	/*
	 * ELF file operation
	 */
	hdr = (Elf32_Ehdr *)in_data;
	if (bcmp(hdr->e_ident, ELFMAG, SELFMAG)) {
		fprintf(stderr, "input '%s' is not ELF32 format\n", argv[1]);
		exit(3);
	}
	if (_BE_short(hdr->e_machine) != EM_PPC) {
		fprintf(stderr, "input '%s' is not PowerPC exec binary\n",
			argv[1]);
		exit(3);
	}

#ifdef DEBUG
	printf("e_entry= 0x%lx\n", _BE_long(hdr->e_entry));
	printf("e_phoff= 0x%lx\n", _BE_long(hdr->e_phoff));
	printf("e_shoff= 0x%lx\n", _BE_long(hdr->e_shoff));
	printf("e_flags= 0x%x\n", _BE_short(hdr->e_flags));
	printf("e_ehsize= 0x%x\n", _BE_short(hdr->e_ehsize));
	printf("e_phentsize= 0x%x\n", _BE_short(hdr->e_phentsize));
	printf("e_phnum= 0x%x\n", _BE_short(hdr->e_phnum));
	printf("e_shentsize= 0x%x\n", _BE_short(hdr->e_shentsize));
	printf("e_shnum= 0x%x\n", _BE_short(hdr->e_shnum));
	printf("e_shstrndx= 0x%x\n", _BE_short(hdr->e_shstrndx));
	printf("\n");
#endif

	shdr = (Elf32_Shdr *)(in_data + _BE_long(hdr->e_shoff) +
		sizeof (*shdr) * _BE_short(hdr->e_shstrndx));
	symtab = (char *)(in_data + _BE_long(shdr->sh_offset));

	for (i = 0; i < _BE_short(hdr->e_shnum); i++) {
		shdr = (Elf32_Shdr *)(in_data + _BE_long(hdr->e_shoff) +
			sizeof (*shdr) * i);

#ifdef DEBUG
		printf("sh_name= 0x%lx(%s)\n", _BE_long(shdr->sh_name),
			&symtab[_BE_long(shdr->sh_name)]);
		printf("sh_type= 0x%lx\n", _BE_long(shdr->sh_type));
		printf("sh_flags= 0x%lx\n", _BE_long(shdr->sh_flags));
		printf("sh_addr= 0x%lx\n", _BE_long(shdr->sh_addr));
		printf("sh_offset= 0x%lx\n", _BE_long(shdr->sh_offset));
		printf("sh_size= 0x%lx\n", _BE_long(shdr->sh_size));
		printf("sh_link= 0x%lx\n", _BE_long(shdr->sh_link));
		printf("sh_info= 0x%lx\n", _BE_long(shdr->sh_info));
		printf("sh_addralign= 0x%lx\n", _BE_long(shdr->sh_addralign));
		printf("sh_entsize= 0x%lx\n", _BE_long(shdr->sh_entsize));
		printf("\n");
#endif

		if (!strcmp(&symtab[_BE_long(shdr->sh_name)], ".sbss")) {
			sbss_end = _BE_long(shdr->sh_addr) +
				_BE_long(shdr->sh_size);
		}
		if (!strcmp(&symtab[_BE_long(shdr->sh_name)], ".bss")) {
			bss_end = _BE_long(shdr->sh_addr) +
				_BE_long(shdr->sh_size);
		}
	}

	for (i = 0; i < _BE_short(hdr->e_phnum); i++) {
		phdr = (Elf32_Phdr *)(in_data + _BE_long(hdr->e_phoff) +
			sizeof (*phdr) * i);

#ifdef DEBUG
		printf("p_type= 0x%lx\n", _BE_long(phdr->p_type));
		printf("p_offset= 0x%lx\n", _BE_long(phdr->p_offset));
		printf("p_vaddr= 0x%lx\n", _BE_long(phdr->p_vaddr));
		printf("p_paddr= 0x%lx\n", _BE_long(phdr->p_paddr));
		printf("p_filesz= 0x%lx\n", _BE_long(phdr->p_filesz));
		printf("p_memsz= 0x%lx\n", _BE_long(phdr->p_memsz));
		printf("p_flags= 0x%lx\n", _BE_long(phdr->p_flags));
		printf("p_align= 0x%lx\n", _BE_long(phdr->p_align));
		printf("\n");
#endif

		if (_BE_long(phdr->p_filesz) < _BE_long(phdr->p_memsz)) {
			p_memsz = _BE_long(_BE_long(phdr->p_memsz) +
				bss_end - sbss_end);
			p_memsz_offset = (int)&phdr->p_memsz - (int)in_data;
		}
	}

	if (write(out_fd, in_data, p_memsz_offset) < 0) {
		perror("write");
		exit(1);
	}
	if (write(out_fd, &p_memsz, sizeof (p_memsz)) < 0) {
		perror("write");
		exit(1);
	}
	if (write(out_fd, in_data + p_memsz_offset + sizeof (p_memsz),
	    buf.st_size - p_memsz_offset - sizeof (p_memsz)) < 0) {
		perror("write");
		exit(1);
	}

	close(in_fd);
	close(out_fd);
	return 0;
}