first commit

This commit is contained in:
Dan Peori
2010-10-18 12:54:49 -03:00
commit 8a3bef9012
612 changed files with 74685 additions and 0 deletions

23
tools/Makefile.am Normal file
View File

@@ -0,0 +1,23 @@
bin_PROGRAMS = bin2s bin2c bin2o pack-pbp unpack-pbp mksfo mksfoex psp-config psp-build-exports psp-prxgen psp-fixup-imports
bin2s_SOURCES = bin2s.c
bin2c_SOURCES = bin2c.c
bin2o_SOURCES = bin2o.c
pack_pbp_SOURCES = pack-pbp.c
unpack_pbp_SOURCES = unpack-pbp.c
mksfo_SOURCES = mksfo.c
mksfoex_SOURCES = mksfoex.c
psp_config_SOURCES = psp-config.c getopt_long.c
psp_build_exports_SOURCES = psp-build-exports.c getopt_long.c sha1.c
psp_prxgen_SOURCES = psp-prxgen.c getopt_long.c
psp_fixup_imports_SOURCES = psp-fixup-imports.c getopt_long.c sha1.c
noinst_HEADERS = elftypes.h getopt.h prxtypes.h sha1.h types.h

73
tools/bin2c.c Normal file
View File

@@ -0,0 +1,73 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| | ___| ____| | \ PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# Review pspsdk README & LICENSE files for further details.
#
# $Id: bin2c.c 210 2005-06-18 17:52:59Z mrbrown $
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
unsigned char *buffer;
int main(int argc, char *argv[])
{
int fd_size;
FILE *source,*dest;
int i;
if(argc != 4) {
printf("bin2c - from bin2s By Sjeep\n"
"Usage: bin2c infile outfile label\n\n");
return 1;
}
if((source=fopen( argv[1], "rb")) == NULL) {
printf("Error opening %s for reading.\n",argv[1]);
return 1;
}
fseek(source,0,SEEK_END);
fd_size = ftell(source);
fseek(source,0,SEEK_SET);
buffer = malloc(fd_size);
if(buffer == NULL) {
printf("Failed to allocate memory.\n");
return 1;
}
if(fread(buffer,1,fd_size,source) != fd_size) {
printf("Failed to read file.\n");
return 1;
}
fclose(source);
if((dest = fopen(argv[2],"w+")) == NULL) {
printf("Failed to open/create %s.\n",argv[2]);
return 1;
}
fprintf(dest, "#ifndef __%s__\n", argv[3]);
fprintf(dest, "#define __%s__\n\n", argv[3]);
fprintf(dest, "static unsigned int size_%s = %d;\n", argv[3], fd_size);
fprintf(dest, "static unsigned char %s[] __attribute__((aligned(16))) = {", argv[3]);
for(i=0;i<fd_size;i+=1) {
if((i % 16) == 0) fprintf(dest, "\n\t");
fprintf(dest, "0x%02x, ", buffer[i]);
}
fprintf(dest, "\n};\n\n#endif\n");
fclose(dest);
return 0;
}

385
tools/bin2o.c Normal file
View File

@@ -0,0 +1,385 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| | ___| ____| | \ PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# Review pspsdk README & LICENSE files for further details.
#
# $Id: bin2o.c 1988 2006-08-06 12:06:54Z chip $
# Convets any file into a PSP's .o file.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
int alignment = 16;
int have_size = 1;
int have_irx = 0;
u32 LE32(u32 b) {
u32 t = 0x12345678;
if (*((unsigned char*)(&t)) == 0x78) {
return b;
} else {
return ((b & 0xff000000) >> 24) |
((b & 0x00ff0000) >> 8 ) |
((b & 0x0000ff00) << 8 ) |
((b & 0x000000ff) << 24);
}
}
u16 LE16(u16 b) {
u32 t = 0x12345678;
if (*((unsigned char*)(&t)) == 0x78) {
return b;
} else {
return ((b & 0xff00) >> 8) |
((b & 0x00ff) << 8);
}
}
unsigned char elf_header[] = {
0x7f, 'E', 'L', 'F', 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // e_ident
0x01, 0x00, // e_type (relocatable)
0x08, 0x00, // e_machine (mips)
0x01, 0x00, 0x00, 0x00, // e_version
0x00, 0x00, 0x00, 0x00, // e_entry
0x00, 0x00, 0x00, 0x00, // e_phoff
0x34, 0x00, 0x00, 0x00, // e_shoff
0x01, 0x40, 0x92, 0x20, // e_flags
0x34, 0x00, // e_ehsize
0x00, 0x00, // e_phentsize
0x00, 0x00, // e_phnum
0x28, 0x00, // e_shentsize
0x05, 0x00, // e_shnum
0x01, 0x00, // e_shstrndx
};
// 0 = NULL
// 1 = .shstrtab
// 2 = .symtab
// 3 = .strtab
// 4 = .data
struct elf_section_t {
u32 sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size;
u32 sh_link, sh_info, sh_addralign, sh_entsize;
};
struct elf_symbol_t {
u32 st_name, st_value, st_size;
u8 st_info, st_other;
u16 st_shndx;
};
// 0 0000000001 11111111 12222222 22233
// 0 1234567890 12345678 90123456 78901
char shstrtab[] = "\0.shstrtab\0.symtab\0.strtab\0.data";
void create_elf(FILE * dest, const unsigned char * source, u32 size, const char * label) {
int i, l_size;
struct elf_section_t section;
struct elf_symbol_t symbol;
u32 strtab_size;
char strtab[512];
u32 data_size[4];
if (have_irx) {
elf_header[36] = 1;
elf_header[37] = 0;
elf_header[38] = 0;
elf_header[39] = 0;
}
for (i = 0; i < sizeof(elf_header); i++) {
fputc(elf_header[i], dest);
}
l_size = strlen(label);
strtab[0] = 0;
strcpy(strtab + 1, label);
strcat(strtab + 1, "_start");
strcpy(strtab + 1 + l_size + 7, label);
strcat(strtab + 1 + l_size + 7, "_end");
if (have_size) {
strtab_size = (l_size * 3 + 1 + 7 + 5 + 6);
strcpy(strtab + 1 + l_size + 7 + l_size + 5, label);
strcat(strtab + 1 + l_size + 7 + l_size + 5, "_size");
} else {
strtab_size = (l_size * 2 + 1 + 7 + 5);
}
// section 0 (NULL)
section.sh_name = section.sh_type = section.sh_flags = section.sh_addr = section.sh_offset = section.sh_size =
section.sh_link = section.sh_info = section.sh_addralign = section.sh_entsize = 0;
fwrite(&section, 1, sizeof(section), dest);
// section 1 (.shstrtab)
section.sh_name = LE32(1);
section.sh_type = LE32(3); // STRTAB
section.sh_flags = 0;
section.sh_addr = 0;
section.sh_offset = LE32(40 * 5 + 0x34);
section.sh_size = LE32(33);
section.sh_link = 0;
section.sh_info = 0;
section.sh_addralign = LE32(1);
section.sh_entsize = 0;
fwrite(&section, 1, sizeof(section), dest);
// section 2 (.symtab)
section.sh_name = LE32(11);
section.sh_type = LE32(2); // SYMTAB
section.sh_flags = 0;
section.sh_addr = 0;
section.sh_offset = LE32(40 * 5 + 0x34 + 33);
section.sh_size = LE32(have_size ? 0x30 : 0x20);
section.sh_link = LE32(3);
section.sh_info = 0;
section.sh_addralign = LE32(4);
section.sh_entsize = LE32(0x10);
fwrite(&section, 1, sizeof(section), dest);
// section 3 (.strtab)
section.sh_name = LE32(19);
section.sh_type = LE32(3); // STRTAB
section.sh_flags = 0;
section.sh_addr = 0;
section.sh_offset = LE32(40 * 5 + 0x34 + 33 + (have_size ? 0x30 : 0x20));
section.sh_size = LE32(strtab_size);
section.sh_link = 0;
section.sh_info = 0;
section.sh_addralign = LE32(1);
section.sh_entsize = 0;
fwrite(&section, 1, sizeof(section), dest);
// section 4 (.data)
section.sh_name = LE32(27);
section.sh_type = LE32(1); // PROGBITS
section.sh_flags = LE32(3); // Write + Alloc
section.sh_addr = 0;
section.sh_offset = LE32(40 * 5 + 0x34 + 33 + (have_size ? 0x30 : 0x20) + strtab_size);
section.sh_size = LE32(size + have_size * 16);
section.sh_link = 0;
section.sh_addralign = LE32(alignment);
section.sh_entsize = 0;
fwrite(&section, 1, sizeof(section), dest);
fwrite(shstrtab, 1, 33, dest);
symbol.st_name = LE32(1);
symbol.st_value = LE32(have_size * 16);
symbol.st_size = LE32(size);
symbol.st_info = 0x11;
symbol.st_other = 0;
symbol.st_shndx = LE16(4);
fwrite(&symbol, 1, sizeof(symbol), dest);
symbol.st_name = LE32(l_size + 1 + 7);
symbol.st_value = LE32(size + have_size * 16);
symbol.st_size = 0;
symbol.st_info = 0x11;
symbol.st_other = 0;
symbol.st_shndx = LE16(4);
fwrite(&symbol, 1, sizeof(symbol), dest);
if (have_size) {
symbol.st_name = LE32(l_size * 2 + 1 + 7 + 5);
symbol.st_value = 0;
symbol.st_size = LE32(4);
symbol.st_info = 0x11;
symbol.st_other = 0;
symbol.st_shndx = LE16(4);
fwrite(&symbol, 1, sizeof(symbol), dest);
}
fwrite(strtab, 1, strtab_size, dest);
if (have_size) {
data_size[0] = LE32(size);
data_size[1] = 0;
data_size[2] = 0;
data_size[3] = 0;
fwrite(data_size, 4, 4, dest);
}
fwrite(source, 1, size, dest);
}
void usage() {
printf("bin2o - Converts a binary file into a .o file.\n"
"Usage: bin2o [-a XX] [-n] [-i] [-b XX] [-e XX] [-s XX] infile outfile label\n"
" -i - create an iop-compatible .o file.\n"
" -n - don't add label_size symbol.\n"
" -a XX - set .data section alignment to XX.\n"
" (has to be a power of two).\n"
" -b XX - start reading file at this offset.\n"
" -e XX - stop reading file at this offset.\n"
" -s XX - force output data to be of this size.\n"
"\n"
);
}
int main(int argc, char *argv[])
{
u32 fd_size, start = 0, end = 0xffffffff, size = 0xffffffff;
unsigned char * buffer;
FILE * source, * dest;
char * f_source = 0, * f_dest = 0, * f_label = 0;
int i;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'a':
i++;
if (!argv[i]) {
usage();
printf("-a requires an argument.\n");
return 1;
}
if (argv[i][0] == '-') {
usage();
printf("-a requires an argument.\n");
return 1;
}
alignment = atoi(argv[i]);
if ((alignment - 1) & alignment) {
printf("Error: alignment must be a power of 2.\n");
return 1;
}
break;
case 'n':
have_size = 0;
break;
case 'i':
have_irx = 1;
break;
case 'b':
i++;
if (!argv[i]) {
usage();
printf("-b requires an argument.\n");
return 1;
}
if (argv[i][0] == '-') {
usage();
printf("-b requires an argument.\n");
return 1;
}
start = atoi(argv[i]);
break;
case 'e':
i++;
if (!argv[i]) {
usage();
printf("-e requires an argument.\n");
return 1;
}
if (argv[i][0] == '-') {
usage();
printf("-e requires an argument.\n");
return 1;
}
end = atoi(argv[i]);
break;
case 's':
i++;
if (!argv[i]) {
usage();
printf("-s requires an argument.\n");
return 1;
}
if (argv[i][0] == '-') {
usage();
printf("-s requires an argument.\n");
return 1;
}
size = atoi(argv[i]);
break;
default:
usage();
printf("Unknow option: %s.\n", argv[i]);
return 1;
}
} else {
if (!f_source) {
f_source = argv[i];
} else if (!f_dest) {
f_dest = argv[i];
} else if (!f_label) {
f_label = argv[i];
} else {
usage();
printf("Too many arguments.\n");
return 1;
}
}
}
if (!f_source || !f_dest || !f_label) {
usage();
printf("Not enough arguments.\n");
return 1;
}
if (!(source = fopen(f_source, "rb"))) {
printf("Error opening %s for reading.\n", f_source);
return 1;
}
fseek(source, 0, SEEK_END);
fd_size = ftell(source);
fseek(source, start, SEEK_SET);
if (fd_size < end)
end = fd_size;
if (end < (size - start))
size = end - start;
buffer = malloc(size);
if (buffer == NULL) {
printf("Failed to allocate memory.\n");
return 1;
}
if (fread(buffer, 1, size, source) != size) {
printf("Failed to read file.\n");
return 1;
}
fclose(source);
if (!(dest = fopen(f_dest, "wb+"))) {
printf("Failed to open/create %s.\n", f_dest);
return 1;
}
create_elf(dest, buffer, size, f_label);
fclose(dest);
free(buffer);
return 0;
}

75
tools/bin2s.c Normal file
View File

@@ -0,0 +1,75 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| | ___| ____| | \ PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# Review pspsdk README & LICENSE files for further details.
#
# $Id: bin2s.c 210 2005-06-18 17:52:59Z mrbrown $
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
unsigned char *buffer;
int main(int argc, char *argv[])
{
int fd_size;
FILE *source,*dest;
int i;
if(argc != 4) {
printf("bin2s - By Sjeep\n"
"Usage: bin2s infile outfile label\n\n");
return 1;
}
if((source=fopen( argv[1], "rb")) == NULL) {
printf("Error opening %s for reading.\n",argv[1]);
return 1;
}
fseek(source,0,SEEK_END);
fd_size = ftell(source);
fseek(source,0,SEEK_SET);
buffer = malloc(fd_size);
if(buffer == NULL) {
printf("Failed to allocate memory.\n");
return 1;
}
if(fread(buffer,1,fd_size,source) != fd_size) {
printf("Failed to read file.\n");
return 1;
}
fclose(source);
if((dest = fopen(argv[2],"w+")) == NULL) {
printf("Failed to open/create %s.\n",argv[2]);
return 1;
}
fprintf(dest, ".sdata\n\n");
fprintf(dest, ".globl size_%s\nsize_%s:\t.word %d\n\n", argv[3], argv[3], fd_size);
fprintf(dest, ".data\n\n");
fprintf(dest, ".balign 16\n\n");
fprintf(dest, ".globl %s\n",argv[3]);
fprintf(dest, "%s:\n\n",argv[3]);
for(i=0;i<fd_size;i++) {
if((i % 16) == 0) fprintf(dest, "\n\t.byte 0x%02x", buffer[i]);
else fprintf(dest, ", 0x%02x", buffer[i]);
}
fprintf(dest, "\n");
fclose(dest);
return 0;
}

246
tools/elftypes.h Normal file
View File

@@ -0,0 +1,246 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* elftypes.h - Definitions for the different ELF types.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: elftypes.h 1520 2005-12-04 20:09:36Z tyranid $
*/
#ifndef __ELF_TYPES_H__
#define __ELF_TYPES_H__
#include "types.h"
#define ELF_MACHINE_MIPS 0x0008
#define ELF_SH_STRTAB ".shstrtab"
#define ELF_SECT_MAX_NAME 128
/* Structure defining a single elf section */
struct ElfSection
{
/* Name index */
u32 iName;
/* Type of section */
u32 iType;
/* Section flags */
u32 iFlags;
/* Addr of section when loaded */
u32 iAddr;
/* Offset of the section in the elf */
u32 iOffset;
/* Size of the sections data */
u32 iSize;
/* Link info */
u32 iLink;
/* Info */
u32 iInfo;
/* Address alignment */
u32 iAddralign;
/* Entry size */
u32 iEntsize;
/* Aliased pointer to the data (in the original Elf) */
u8 *pData;
/* Name of the section */
char szName[ELF_SECT_MAX_NAME];
/* Index */
int iIndex;
/* Section Ref. Used for relocations */
struct ElfSection *pRef;
/* Indicates if this section is to be outputted */
int blOutput;
};
struct ElfProgram
{
u32 iType;
u32 iOffset;
u32 iVaddr;
u32 iPaddr;
u32 iFilesz;
u32 iMemsz;
u32 iFlags;
u32 iAlign;
/* Aliased pointer to the data (in the original Elf)*/
u8 *pData;
};
/* Structure to hold elf header data, in native format */
struct ElfHeader
{
u32 iMagic;
u32 iClass;
u32 iData;
u32 iIdver;
u32 iType;
u32 iMachine;
u32 iVersion;
u32 iEntry;
u32 iPhoff;
u32 iShoff;
u32 iFlags;
u32 iEhsize;
u32 iPhentsize;
u32 iPhnum;
u32 iShentsize;
u32 iShnum;
u32 iShstrndx;
};
struct ElfReloc
{
/* Pointer to the section name */
const char* secname;
/* Base address */
u32 base;
/* Type */
u32 type;
/* Symbol (if known) */
u32 symbol;
/* Offset into the file */
u32 offset;
/* New Address for the relocation (to do with what you will) */
u32 addr;
};
/* Define ELF types */
typedef u32 Elf32_Addr;
typedef u16 Elf32_Half;
typedef u32 Elf32_Off;
typedef s32 Elf32_Sword;
typedef u32 Elf32_Word;
#define ELF_MAGIC 0x464C457F
#define ELF_EXEC_TYPE 0x0002
#define ELF_PRX_TYPE 0xFFA0
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff
#define SHT_PRXRELOC (SHT_LOPROC | 0xA0)
// MIPS Reloc Entry Types
#define R_MIPS_NONE 0
#define R_MIPS_16 1
#define R_MIPS_32 2
#define R_MIPS_REL32 3
#define R_MIPS_26 4
#define R_MIPS_HI16 5
#define R_MIPS_LO16 6
#define R_MIPS_GPREL16 7
#define R_MIPS_LITERAL 8
#define R_MIPS_GOT16 9
#define R_MIPS_PC16 10
#define R_MIPS_CALL16 11
#define R_MIPS_GPREL32 12
#define SHF_WRITE 1
#define SHF_ALLOC 2
#define SHF_EXECINSTR 4
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7fffffff
/* ELF file header */
typedef struct {
Elf32_Word e_magic;
u8 e_class;
u8 e_data;
u8 e_idver;
u8 e_pad[9];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} __attribute__((packed)) Elf32_Ehdr;
/* ELF section header */
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} __attribute__((packed)) Elf32_Shdr;
typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
#define ELF32_R_SYM(i) ((i)>>8)
#define ELF32_R_TYPE(i) ((u8)(i&0xFF))
typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
typedef struct {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} __attribute__((packed)) Elf32_Sym;
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STB_LOPROC 13
#define STB_HIPROC 15
#define ELF32_ST_BIND(i) ((i)>>4)
#define ELF32_ST_TYPE(i) ((i)&0xf)
#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
#endif

68
tools/getopt.h Normal file
View File

@@ -0,0 +1,68 @@
/* $NetBSD: getopt.h,v 1.7 2005/02/03 04:39:32 perry Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _GETOPT_H_
#define _GETOPT_H_
#include <unistd.h>
#define no_argument 0
#define required_argument 1
#define optional_argument 2
extern char *optarg;
extern int optind, opterr, optopt;
struct option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};
int getopt_long(int, char * const *, const char *,
const struct option *, int *);
#endif /* !_GETOPT_H_ */

405
tools/getopt_long.c Normal file
View File

@@ -0,0 +1,405 @@
/* $NetBSD: getopt_long.c,v 1.19 2005/12/02 14:08:51 yamt Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <errno.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define IGNORE_FIRST (*options == '-' || *options == '+')
#define PRINT_ERROR ((opterr) && ((*options != ':') \
|| (IGNORE_FIRST && options[1] != ':')))
#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
/* XXX: GNU ignores PC if *options == '-' */
#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
/* return values */
#define BADCH (int)'?'
#define BADARG ((IGNORE_FIRST && options[1] == ':') \
|| (*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#define EMSG ""
static int getopt_internal (int, char **, const char *);
static int gcd (int, int);
static void permute_args (int, int, int, char **);
static const char *place = EMSG; /* option letter processing */
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c";
static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s";
static const char noarg[] = "option doesn't take an argument -- %.*s";
static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(a, b)
int a;
int b;
{
int c;
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return b;
}
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(int panonopt_start, int panonopt_end, int opt_end, char **nargv)
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
nargv[pos] = nargv[cstart];
nargv[cstart] = swap;
}
}
}
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
* Returns -2 if -- is found (can be long option or end of options marker).
*/
static int
getopt_internal(int nargc, char **nargv, const char *options)
{
char *oli; /* option letter list index */
int optchar;
optarg = NULL;
/*
* XXX Some programs (like rsyncd) expect to be able to
* XXX re-initialize optind to 0 and have getopt_long(3)
* XXX properly function again. Work around this braindamage.
*/
if (optind == 0)
optind = 1;
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return -1;
}
if ((*(place = nargv[optind]) != '-')
|| (place[1] == '\0')) { /* found non-option */
place = EMSG;
if (IN_ORDER) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return INORDER;
}
if (!PERMUTE) {
/*
* if no permutation wanted, stop parsing
* at first non-option
*/
return -1;
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
if (place[1] && *++place == '-') { /* found "--" */
place++;
return -2;
}
}
if ((optchar = (int)*place++) == (int)':' ||
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
/* option letter unknown or ':' */
if (!*place)
++optind;
if (PRINT_ERROR)
fprintf(stderr, illoptchar, optchar);
optopt = optchar;
return BADCH;
}
if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
/* XXX: what if no long options provided (called by getopt)? */
if (*place)
return -2;
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
fprintf(stderr, recargchar, optchar);
optopt = optchar;
return BADARG;
} else /* white space */
place = nargv[optind];
/*
* Handle -W arg the same as --arg (which causes getopt to
* stop parsing).
*/
return -2;
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = (char *) place;
/* XXX: disable test for :: if PC? (GNU doesn't) */
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
fprintf(stderr, recargchar, optchar);
optopt = optchar;
return BADARG;
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return optchar;
}
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx)
{
int retval;
retval = getopt_internal(nargc, (char **) (nargv), options);
if (retval == -2) {
char *current_argv, *has_equal;
size_t current_argv_len;
int i, match;
current_argv = (char *) (place);
match = -1;
optind++;
place = EMSG;
if (*current_argv == '\0') { /* found "--" */
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, (char **) (nargv));
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return -1;
}
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
if (strlen(long_options[i].name) ==
(unsigned)current_argv_len) {
/* exact match */
match = i;
break;
}
if (match == -1) /* partial match */
match = i;
else {
/* ambiguous abbreviation */
if (PRINT_ERROR)
fprintf(stderr, ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return BADCH;
}
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
fprintf(stderr, noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of
* flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return BADARG;
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use
* next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':'
* indicates no error should be generated
*/
if (PRINT_ERROR)
fprintf(stderr, recargstring, current_argv);
/*
* XXX: GNU sets optopt to val regardless
* of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return BADARG;
}
} else { /* unknown option */
if (PRINT_ERROR)
fprintf(stderr, illoptstring, current_argv);
optopt = 0;
return BADCH;
}
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
retval = 0;
} else
retval = long_options[match].val;
if (idx)
*idx = match;
}
return retval;
}

78
tools/mksfo.c Normal file
View File

@@ -0,0 +1,78 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| | ___| ____| | \ PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# Review ps2sdk README & LICENSE files for further details.
#
# A simple tool to build an SFO file for use in the EBOOT.PBP
# $Id: mksfo.c 1993 2006-08-23 21:40:16Z jim $
*/
#include <stdio.h>
#include <string.h>
#define SIZE_POS 0x88
#define TITLE_POS 0x118
#define TITLE_SIZE 0x7F
/* A default, simple SFO file */
unsigned char g_defaultSfo[] = {
0x00, 0x50, 0x53, 0x46, 0x01, 0x01, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x04, 0x02, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x04, 0x02, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x04, 0x02, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x27, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x36, 0x00, 0x04, 0x02, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x45, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x2c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x04, 0x02, 0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0x42, 0x4f, 0x4f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x00, 0x43, 0x41, 0x54,
0x45, 0x47, 0x4f, 0x52, 0x59, 0x00, 0x44, 0x49, 0x53, 0x43, 0x5f, 0x49, 0x44, 0x00, 0x44, 0x49,
0x53, 0x43, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x00, 0x50, 0x41, 0x52, 0x45, 0x4e,
0x54, 0x41, 0x4c, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x00, 0x50, 0x53, 0x50, 0x5f, 0x53, 0x59,
0x53, 0x54, 0x45, 0x4d, 0x5f, 0x56, 0x45, 0x52, 0x00, 0x52, 0x45, 0x47, 0x49, 0x4f, 0x4e, 0x00,
0x54, 0x49, 0x54, 0x4c, 0x45, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x47, 0x00, 0x00,
0x55, 0x43, 0x4a, 0x53, 0x31, 0x30, 0x30, 0x34, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x31, 0x2e, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x30, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int main(int argc, char **argv)
{
FILE *fp;
int len;
if(argc < 3)
{
fprintf(stderr, "Usage: mksfo TITLE output.sfo\n");
return 1;
}
len = strlen(argv[1]);
if(len > TITLE_SIZE) len = TITLE_SIZE;
g_defaultSfo[SIZE_POS] = (unsigned char) len;
strncpy((char *) &g_defaultSfo[TITLE_POS], argv[1], len);
fp = fopen(argv[2], "wb");
if(fp != NULL)
{
fwrite(g_defaultSfo, 1, sizeof(g_defaultSfo), fp);
fclose(fp);
}
else
{
fprintf(stderr, "Could not open %s\n", argv[2]);
return 1;
}
return 0;
}

341
tools/mksfoex.c Normal file
View File

@@ -0,0 +1,341 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| | ___| ____| | \ PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# Review pspsdk README & LICENSE files for further details.
#
# New and improved mksfo
# $Id$
*/
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include "types.h"
#define PSF_MAGIC 0x46535000
#define PSF_VERSION 0x00000101
struct SfoHeader
{
uint32_t magic;
uint32_t version;
uint32_t keyofs;
uint32_t valofs;
uint32_t count;
} __attribute__((packed));
struct SfoEntry
{
uint16_t nameofs;
uint8_t alignment;
uint8_t type;
uint32_t valsize;
uint32_t totalsize;
uint32_t dataofs;
} __attribute__((packed));
#define PSF_TYPE_BIN 0
#define PSF_TYPE_STR 2
#define PSF_TYPE_VAL 4
struct EntryContainer
{
const char *name;
int type;
uint32_t value;
const char *data;
};
struct EntryContainer g_defaults[] = {
{ "BOOTABLE", PSF_TYPE_VAL, 1, NULL },
{ "CATEGORY", PSF_TYPE_STR, 0, "MG" },
{ "DISC_ID", PSF_TYPE_STR, 0, "UCJS10041" },
{ "DISC_VERSION", PSF_TYPE_STR, 0, "1.00" },
{ "PARENTAL_LEVEL", PSF_TYPE_VAL, 1, NULL },
{ "PSP_SYSTEM_VER", PSF_TYPE_STR, 0, "1.00" },
{ "REGION", PSF_TYPE_VAL, 0x8000, NULL },
};
#define MAX_OPTIONS (256)
static const char *g_title = NULL;
static const char *g_filename = NULL;
static int g_empty = 0;
static struct EntryContainer g_vals[MAX_OPTIONS];
static struct option arg_opts[] =
{
{"dword", required_argument, NULL, 'd'},
{"string", required_argument, NULL, 's'},
{"empty", no_argument, NULL, 'e'},
{ NULL, 0, NULL, 0 }
};
struct EntryContainer *find_free()
{
int i;
for(i = 0; i < MAX_OPTIONS; i++)
{
if(g_vals[i].name == NULL)
{
return &g_vals[i];
}
}
return NULL;
}
struct EntryContainer *find_name(const char *name)
{
int i;
for(i = 0; i < MAX_OPTIONS; i++)
{
if((g_vals[i].name != NULL) && (strcmp(g_vals[i].name, name) == 0))
{
return &g_vals[i];
}
}
return NULL;
}
int add_string(char *str)
{
char *equals = NULL;
struct EntryContainer *entry;
equals = strchr(str, '=');
if(equals == NULL)
{
fprintf(stderr, "Invalid option (no =)\n");
return 0;
}
*equals++ = 0;
entry = find_free();
if(entry == NULL)
{
fprintf(stderr, "Maximum options reached\n");
return 0;
}
memset(entry, 0, sizeof(struct EntryContainer));
entry->name = str;
entry->type = PSF_TYPE_STR;
entry->data = equals;
return 1;
}
int add_dword(char *str)
{
char *equals = NULL;
struct EntryContainer *entry;
equals = strchr(str, '=');
if(equals == NULL)
{
fprintf(stderr, "Invalid option (no =)\n");
return 0;
}
*equals++ = 0;
entry = find_free();
if(entry == NULL)
{
fprintf(stderr, "Maximum options reached\n");
return 0;
}
memset(entry, 0, sizeof(struct EntryContainer));
entry->name = str;
entry->type = PSF_TYPE_VAL;
entry->value = strtoul(equals, NULL, 0);
return 1;
}
/* Process the arguments */
int process_args(int argc, char **argv)
{
int ch;
g_title = NULL;
g_filename = NULL;
g_empty = 0;
ch = getopt_long(argc, argv, "ed:s:", arg_opts, NULL);
while(ch != -1)
{
switch(ch)
{
case 'd' : if(!add_dword(optarg))
{
return 0;
}
break;
case 's' : if(!add_string(optarg))
{
}
break;
default : break;
};
ch = getopt_long(argc, argv, "ed:s:", arg_opts, NULL);
}
argc -= optind;
argv += optind;
if(argc < 1)
{
return 0;
}
if(!g_empty)
{
g_title = argv[0];
argc--;
argv++;
}
if(argc < 1)
{
return 0;
}
g_filename = argv[0];
return 1;
}
int main(int argc, char **argv)
{
FILE *fp;
int i;
char head[8192];
char keys[8192];
char data[8192];
struct SfoHeader *h;
struct SfoEntry *e;
char *k;
char *d;
unsigned int align;
unsigned int keyofs;
unsigned int count;
if(!process_args(argc, argv))
{
fprintf(stderr, "Usage: mksfoex [options] TITLE output.sfo\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, "-d NAME=VALUE - Add a new DWORD value\n");
fprintf(stderr, "-s NAME=STR - Add a new string value\n");
return 1;
}
if(!g_empty)
{
struct EntryContainer *entry;
for(i = 0; i < (sizeof(g_defaults) / sizeof(struct EntryContainer)); i++)
{
if(!find_name(g_defaults[i].name))
{
entry = find_free();
if(entry == NULL)
{
fprintf(stderr, "Maximum options reached\n");
return 0;
}
*entry = g_defaults[i];
}
}
if(!find_name("TITLE"))
{
entry = find_free();
entry->name = "TITLE";
entry->type = PSF_TYPE_STR;
entry->value = 0;
entry->data = g_title;
}
}
memset(head, 0, sizeof(head));
memset(keys, 0, sizeof(keys));
memset(data, 0, sizeof(data));
h = (struct SfoHeader*) head;
e = (struct SfoEntry*) (head+sizeof(struct SfoHeader));
k = keys;
d = data;
SW(&h->magic, PSF_MAGIC);
SW(&h->version, PSF_VERSION);
count = 0;
for(i = 0; g_vals[i].name; i++)
{
SW(&h->count, ++count);
SW(&e->nameofs, k-keys);
SW(&e->dataofs, d-data);
SW(&e->alignment, 4);
SW(&e->type, g_vals[i].type);
strcpy(k, g_vals[i].name);
k += strlen(k)+1;
if(e->type == PSF_TYPE_VAL)
{
SW(&e->valsize, 4);
SW(&e->totalsize, 4);
SW((uint32_t*) d, g_vals[i].value);
d += 4;
}
else
{
int totalsize;
int valsize;
valsize = strlen(g_vals[i].data)+1;
totalsize = (valsize + 3) & ~3;
SW(&e->valsize, valsize);
SW(&e->totalsize, totalsize);
memset(d, 0, totalsize);
memcpy(d, g_vals[i].data, valsize);
d += totalsize;
}
e++;
}
keyofs = (char*)e - head;
SW(&h->keyofs, keyofs);
align = 3 - ((unsigned int) (k-keys) & 3);
while(align < 3)
{
k++;
align--;
}
SW(&h->valofs, keyofs + (k-keys));
fp = fopen(g_filename, "wb");
if(fp == NULL)
{
fprintf(stderr, "Cannot open filename %s\n", g_filename);
return 0;
}
fwrite(head, 1, (char*)e-head, fp);
fwrite(keys, 1, k-keys, fp);
fwrite(data, 1, d-data, fp);
fclose(fp);
return 0;
}

189
tools/pack-pbp.c Normal file
View File

@@ -0,0 +1,189 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| | ___| ____| | \ PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 2005 Dan Peori <peori@oopo.net>
# Licenced under Academic Free License version 2.0
# Review pspsdk README & LICENSE files for further details.
#
# 2006-12-30 - Andrew Whatson <whatson@gmail.com>
# - rewrote for easier reading
# - gave "correct" names to UNKNOWN.* files
# - improved memory efficiency with large PBPs
# - output name of each file as it's added
#
# $Id: pack-pbp.c 2228 2007-05-01 05:22:03Z oopo $
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef WORDS_BIGENDIAN
// Swap the bytes of an int for big-endian machines
static int swap_int(int n)
{
return ((n>>24)&0xff)|((n>>8)&0xff00)|((n<<8)&0xff0000)|((n<<24)&0xff000000);
}
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
// Struct to describe the header of a PBP file
struct {
char signature[4];
char version[4];
int offset[8];
} header = {
{ 0x00, 0x50, 0x42, 0x50 },
{ 0x00, 0x00, 0x01, 0x00 },
{ 40, 0, 0, 0, 0, 0, 0, 0 }
};
// Maximum size of read buffer
int maxbuffer = 16 * 1024 * 1024;
int main(int argc, char *argv[]) { int loop0, result;
FILE *infile;
FILE *outfile;
int filesize[8];
// Check for the correct number of arguments
if (argc != 10) {
printf("USAGE: %s <output.pbp> <param.sfo> <icon0.png> <icon1.pmf> <pic0.png> <pic1.png> <snd0.at3> <data.psp> <data.psar>\n", argv[0]);
return -1;
}
// For each file in the PBP
for (loop0 = 0; loop0 < 8; loop0++) {
// If the specificed filename is NULL or -, skip the file.
if (strncmp(argv[2 + loop0], "NULL", 4) == 0 || strncmp(argv[2 + loop0], "-", 4) == 0) {
filesize[loop0] = 0;
} else {
// Open the file
infile = fopen(argv[2 + loop0], "rb");
if (infile == NULL) {
printf("ERROR: Could not open the file. (%s)\n", argv[2 + loop0]);
return -1;
}
// Read in the file size
fseek(infile, 0, SEEK_END);
filesize[loop0] = ftell(infile);
fseek(infile, 0, SEEK_SET);
if (filesize[loop0] < 0) {
printf("ERROR: Could not read in the file size. (%s)\n", argv[2 + loop0]);
return -1;
}
// Close the file
result = fclose(infile);
if (result < 0) {
printf("ERROR: Could not close the file. (%s)\n", argv[2 + loop0]);
return -1;
}
}
}
// Set the header offset values for each file
for (loop0 = 1; loop0 < 8; loop0++) {
header.offset[loop0] = header.offset[loop0 - 1] + filesize[loop0 - 1];
}
#ifdef WORDS_BIGENDIAN
// Swap the bytes of the offsets for big-endian machines
for (loop0 = 0; loop0 < 8; loop0++) {
header.offset[loop0] = swap_int(header.offset[loop0]);
}
#endif
// Open the output file
outfile = fopen(argv[1], "wb");
if (outfile == NULL) {
printf("ERROR: Could not open the output file. (%s)\n", argv[1]);
return -1;
}
// Write out the header
result = fwrite(&header, sizeof(header), 1, outfile);
if (result < 0) {
printf("ERROR: Could not write out the file header. (%s)\n", argv[1]);
return -1;
}
// For each file in the PBP
for (loop0 = 0; loop0 < 8; loop0++) {
void *buffer;
int readsize;
// Print out the file details
printf("[%d] %10d bytes | %s\n", loop0, filesize[loop0], argv[2 + loop0]);
// If this file is empty, skip it
if (!filesize[loop0]) continue;
// Open the file
infile = fopen(argv[2 + loop0], "rb");
if (infile == NULL) {
printf("ERROR: Could not open the file. (%s)\n", argv[2 + loop0]);
return -1;
}
do {
// Make sure we don't exceed the maximum buffer size
if (filesize[loop0] > maxbuffer) {
readsize = maxbuffer;
} else {
readsize = filesize[loop0];
}
filesize[loop0] -= readsize;
// Create the read buffer
buffer = malloc(readsize);
if (buffer == NULL) {
printf("ERROR: Could not allocate the file data space. (%s)\n", argv[2 + loop0]);
return -1;
}
// Read in the data from the file
if (fread(buffer, readsize, 1, infile) < 0) {
printf("ERROR: Could not read in the file data. (%s)\n", argv[2 + loop0]);
return -1;
}
// Write the contents of the buffer to the PBP
if (fwrite(buffer, readsize, 1, outfile) < 0) {
printf("ERROR: Could not write out the file data. (%s)\n", argv[1]);
return -1;
}
// Clean up the buffer
free(buffer);
// Repeat if we haven't finished writing the file
} while (filesize[loop0]);
}
// Close the output file.
result = fclose(outfile);
if (result < 0) {
printf("ERROR: Could not close the output file. (%s)\n", argv[1]);
return -1;
}
// Exit successful
return 0;
}

150
tools/prxtypes.h Normal file
View File

@@ -0,0 +1,150 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* prxtypes.h - Definition of PRX specific types.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: prxtypes.h 1095 2005-09-27 21:02:16Z jim $
*/
#ifndef __PRXTYPES_H__
#define __PRXTYPES_H__
#include "types.h"
#define PSP_MODULE_MAX_NAME 28
#define PSP_LIB_MAX_NAME 128
#define PSP_ENTRY_MAX_NAME 128
/* Define the maximum number of permitted entries per lib */
#define PSP_MAX_V_ENTRIES 255
#define PSP_MAX_F_ENTRIES 65535
#define PSP_MODULE_INFO_NAME ".rodata.sceModuleInfo"
/* Remove the .rel.sceStub.text section as it shouldn't have been there */
#define PSP_MODULE_REMOVE_REL ".rel.sceStub.text"
/* Define a name for the unnamed first export */
#define PSP_SYSTEM_EXPORT "syslib"
enum PspEntryType
{
PSP_ENTRY_FUNC = 0,
PSP_ENTRY_VAR = 1
};
/* Define the in-prx structure types */
/* Structure to hold the module export information */
struct PspModuleExport
{
u32 name;
u32 flags;
u32 counts;
u32 exports;
} __attribute__((packed));
/* Structure to hold the module import information */
struct PspModuleImport
{
u32 name;
u32 flags;
u8 entry_size;
u8 var_count;
u16 func_count;
u32 nids;
u32 funcs;
};
/* Structure to hold the module info */
struct PspModuleInfo
{
u32 flags;
char name[PSP_MODULE_MAX_NAME];
u32 gp;
u32 exports;
u32 exp_end;
u32 imports;
u32 imp_end;
};
/* Define the loaded prx types */
struct PspEntry
{
/* Name of the entry */
char name[PSP_ENTRY_MAX_NAME];
/* Nid of the entry */
u32 nid;
/* Type of the entry */
enum PspEntryType type;
/* Virtual address of the entry in the loaded elf */
u32 addr;
/* Virtual address of the nid dword */
u32 nid_addr;
};
/* Holds a linking entry for an import library */
struct PspLibImport
{
/** Previous import */
struct PspLibImport *prev;
/** Next import */
struct PspLibImport *next;
/** Name of the library */
char name[PSP_LIB_MAX_NAME];
/* Virtual address of the lib import stub */
u32 addr;
/* Copy of the import stub (in native byte order) */
struct PspModuleImport stub;
/* List of function entries */
struct PspEntry funcs[PSP_MAX_F_ENTRIES];
/* Number of function entries */
int f_count;
/* List of variable entried */
struct PspEntry vars[PSP_MAX_V_ENTRIES];
/* Number of variable entires */
int v_count;
};
/* Holds a linking entry for an export library */
struct PspLibExport
{
/** Previous export in the chain */
struct PspLibExport *prev;
/** Next export in the chain */
struct PspLibExport *next;
/** Name of the library */
char name[PSP_LIB_MAX_NAME];
/** Virtual address of the lib import stub */
u32 addr;
/** Copy of the import stub (in native byte order) */
struct PspModuleExport stub;
/** List of function entries */
struct PspEntry funcs[PSP_MAX_F_ENTRIES];
/** Number of function entries */
int f_count;
/** List of variable entried */
struct PspEntry vars[PSP_MAX_V_ENTRIES];
/** Number of variable entires */
int v_count;
};
/** Structure to hold the loaded module information */
struct PspModule
{
/** Name of the module */
char name[PSP_MODULE_MAX_NAME+1];
/** Info structure, in native byte order */
struct PspModuleInfo info;
/** Virtual address of the module info section */
u32 addr;
/** Head of the export list */
struct PspLibExport *exp_head;
/** Head of the import list */
struct PspLibImport *imp_head;
};
#endif

1058
tools/psp-build-exports.c Normal file

File diff suppressed because it is too large Load Diff

290
tools/psp-config.c Normal file
View File

@@ -0,0 +1,290 @@
#if defined(__MINGW32__) && !defined(__CYGWIN__)
#include <windows.h>
#endif
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define PSPDEV_ENV "PSPDEV"
#define PATH_ENV "PATH"
#ifndef MAX_PATH
#define MAX_PATH 256
#endif
/***** Might need to change these for different platforms */
#define PATH_SEP ":"
#define DIR_SEP '/'
#define DIR_SEP_STR "/"
/* The suffix to the path to strip off, if this is not there then we have an error */
#ifdef __MINGW32__
#define PSPDEV_PATH_SUFFIX "/bin/psp-config.exe"
#else
#define PSPDEV_PATH_SUFFIX "/bin/psp-config"
#endif
/************************/
enum PspConfigMode
{
PSP_CONFIG_UNKNOWN,
PSP_CONFIG_PSPSDK_PATH,
PSP_CONFIG_PSPDEV_PATH,
PSP_CONFIG_PSP_PREFIX,
};
/* Specifies that the current usage is to the print the pspsdk path */
static enum PspConfigMode g_configmode;
static struct option arg_opts[] =
{
{"pspsdk-path", no_argument, NULL, 'p'},
{"pspdev-path", no_argument, NULL, 'd'},
{"psp-prefix", no_argument, NULL, 'P'},
{ NULL, 0, NULL, 0 }
};
/* Process the arguments */
int process_args(int argc, char **argv)
{
int ret = 0;
int ch;
g_configmode = PSP_CONFIG_UNKNOWN;
ch = getopt_long(argc, argv, "pdP", arg_opts, NULL);
while(ch != -1)
{
switch(ch)
{
case 'p' : g_configmode = PSP_CONFIG_PSPSDK_PATH;
ret = 1;
break;
case 'd' : g_configmode = PSP_CONFIG_PSPDEV_PATH;
ret = 1;
break;
case 'P' : g_configmode = PSP_CONFIG_PSP_PREFIX;
ret = 1;
break;
default : fprintf(stderr, "Invalid option '%c'\n", ch);
break;
};
ch = getopt_long(argc, argv, "p", arg_opts, NULL);
}
return ret;
}
void print_help(void)
{
fprintf(stderr, "Usage: psp-config [opts]\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, "-p, --pspsdk-path : Print the base directory of PSPSDK\n");
fprintf(stderr, "-d, --pspdev-path : Print the base install directory\n");
fprintf(stderr, "-P, --psp-prefix : Print the prefix of PSP-hosted software\n");
}
void normalize_path (char *out)
{
int i;
int j;
/* Convert "//" to "/" */
for (i = 0; out[i + 1]; i++) {
if (out[i] == '/' && out[i + 1] == '/') {
for (j = i + 1; out[j]; j++) {
out[j] = out[j + 1];
}
i--;
}
}
}
/* Find the path to the pspdev dir (e.g. /usr/local/pspdev) */
char *find_pspdev_path(char *name)
{
static char path[MAX_PATH];
int found = 0;
/* Check if name is an absolute path, if so our job is done */
#ifdef __MINGW32__
char *writableName = malloc(strlen(name) + 2);
char *ptr = writableName;
char temp;
while (*(name)) {
temp = *(name++);
if (temp == '\\') temp = '/';
*(ptr++) = temp;
}
*(ptr) = '\0';
name = writableName;
#endif
if(name[0] == DIR_SEP
#ifdef __MINGW32__
|| name[1] == ':'
#endif
)
{
/* Absolute path */
strncpy(path, name, MAX_PATH);
/* Ensure NUL termination */
path[MAX_PATH-1] = 0;
found = 1;
}
else
{
/* relative path */
if(strchr(name, DIR_SEP) != NULL)
{
if(getcwd(path, MAX_PATH) != NULL)
{
strncat(path, DIR_SEP_STR, MAX_PATH-1);
strncat(path, name, MAX_PATH-1);
found = 1;
}
else
{
fprintf(stderr, "Error getting current working directory\n");
}
}
else
{
char *path_env;
/* Scan the PATH variable */
path_env = getenv(PATH_ENV);
if(path_env != NULL)
{
char *curr_tok;
char new_path[MAX_PATH];
/* Should really use the path separator from the
environment but who on earth changes it? */
curr_tok = strtok(path_env, PATH_SEP);
while(curr_tok != NULL)
{
strcpy(new_path, curr_tok);
strcat(new_path, DIR_SEP_STR);
strcat(new_path, name);
if(access(new_path, X_OK) == 0)
{
found = 1;
strcpy(path, new_path);
break;
}
curr_tok = strtok(NULL, PATH_SEP);
}
}
else
{
fprintf(stderr, "Error, couldn't get PATH environment variable\n");
}
}
}
normalize_path(path);
char *result = NULL;
if(found)
{
int suffix_len;
int path_len;
suffix_len = strlen(PSPDEV_PATH_SUFFIX);
path_len = strlen(path);
if(suffix_len <= path_len)
{
if(strcmp(PSPDEV_PATH_SUFFIX, &path[path_len - suffix_len]) == 0)
{
/* Oki valid path add a NUL */
path[path_len - suffix_len] = 0;
result = path;
}
else
{
fprintf(stderr, "Error, invalid suffix on the end of the path. Should be %s\n", PSPDEV_PATH_SUFFIX);
}
}
else
{
fprintf(stderr, "Error, path not large enough for creating the PSPSDK path\n");
}
}
#ifdef __MINGW32__
free(writableName);
#endif
return result;
}
void print_path(char *name)
{
char *pspdev_env;
pspdev_env = getenv(PSPDEV_ENV);
if(pspdev_env == NULL)
{
/* Could not find the PSPDEV environment variable */
/* Let's try and find where psp-config is */
pspdev_env = find_pspdev_path(name);
}
if (pspdev_env != NULL) {
switch(g_configmode)
{
case PSP_CONFIG_PSPSDK_PATH : printf("%s%c%s\n", pspdev_env, DIR_SEP, PSPSDK_TOPDIR);
break;
case PSP_CONFIG_PSPDEV_PATH : printf("%s\n", pspdev_env);
break;
case PSP_CONFIG_PSP_PREFIX : printf("%s%c%s\n", pspdev_env, DIR_SEP, "psp");
break;
default : fprintf(stderr, "Error, invalida configuration mode\n");
break;
};
}
}
int main(int argc, char **argv)
{
#if defined(__MINGW32__) && !defined(__CYGWIN__)
// this will store the fully-qualified path
char psp_config_path[MAX_PATH] = "";
// fetch the path of the executable
if(GetModuleFileName(0, psp_config_path, sizeof(psp_config_path) - 1) == 0)
{
// fall back
strcpy(psp_config_path, argv[0]);
}
#endif
if(process_args(argc, argv))
{
#if defined(__MINGW32__) && !defined(__CYGWIN__)
print_path(psp_config_path);
#else
print_path(argv[0]);
#endif
}
else
{
print_help();
}
return 0;
}

851
tools/psp-fixup-imports.c Normal file
View File

@@ -0,0 +1,851 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* psp-fixup-imports.c - Simple program to fixup an ELF's imports
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: psp-fixup-imports.c 2324 2007-10-03 00:51:52Z tyranid $
*/
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "types.h"
#include "elftypes.h"
#include "prxtypes.h"
#include "sha1.h"
#define PRX_LIBSTUB_SECT ".lib.stub"
#define PRX_STUBTEXT_SECT ".sceStub.text"
#define PRX_NID_SECT ".rodata.sceNid"
struct NidMap
{
unsigned int oldnid;
unsigned int newnid;
};
#define MAX_MAPNIDS 1024
struct ImportMap
{
struct ImportMap *next;
char name[32];
int count;
/* Could fail on things like PAF but who is going to want to remap 1000+ nids ? */
struct NidMap nids[MAX_MAPNIDS];
};
static const char *g_outfile;
static const char *g_infile;
static const char *g_mapfile;
static unsigned char *g_elfdata = NULL;
static unsigned int g_elfsize;
static struct ElfHeader g_elfhead = {0};
static struct ElfSection *g_elfsections = NULL;
static struct ElfSection *g_modinfo = NULL;
static struct ElfSection *g_libstub = NULL;
static struct ElfSection *g_stubtext = NULL;
static struct ElfSection *g_nid = NULL;
static struct ImportMap *g_map = NULL;
static int g_reversemap = 0;
/* Specifies that the current usage is to the print the pspsdk path */
static int g_verbose = 0;
static struct option arg_opts[] =
{
{"output", required_argument, NULL, 'o'},
{"reverse", no_argument, NULL, 'r' },
{"map", required_argument, NULL, 'm'},
{"verbose", no_argument, NULL, 'v'},
{ NULL, 0, NULL, 0 }
};
/* Process the arguments */
int process_args(int argc, char **argv)
{
int ch;
g_outfile = NULL;
g_infile = NULL;
g_mapfile = NULL;
ch = getopt_long(argc, argv, "vro:m:", arg_opts, NULL);
while(ch != -1)
{
switch(ch)
{
case 'v' : g_verbose = 1;
break;
case 'o' : g_outfile = optarg;
break;
case 'm' : g_mapfile = optarg;
break;
case 'r' : g_reversemap = 1;
break;
default : break;
};
ch = getopt_long(argc, argv, "vro:m:", arg_opts, NULL);
}
argc -= optind;
argv += optind;
if(argc < 1)
{
return 0;
}
g_infile = argv[0];
if(g_outfile == NULL)
{
g_outfile = argv[0];
}
if(g_verbose)
{
fprintf(stderr, "Loading %s, outputting to %s\n", g_infile, g_outfile);
}
return 1;
}
void print_help(void)
{
fprintf(stderr, "Usage: psp-fixup-imports [-v] [-o outfile.elf] infile.elf\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, "-o, --output outfile : Output to a different file\n");
fprintf(stderr, "-m, --map mapfile : Specify a firmware NID mapfile\n");
fprintf(stderr, "-r, --reverse : Reverse the mapping\n");
fprintf(stderr, "-v, --verbose : Verbose output\n");
}
/* Scan through the sections trying to find this address */
const unsigned char *find_data(unsigned int iAddr)
{
int i;
for(i = 0; i < g_elfhead.iShnum; i++)
{
if((g_elfsections[i].iAddr <= iAddr) && ((g_elfsections[i].iAddr + g_elfsections[i].iSize) > iAddr))
{
return g_elfsections[i].pData + (iAddr - g_elfsections[i].iAddr);
}
}
return NULL;
}
struct ImportMap *find_map_by_name(const char *name)
{
struct ImportMap *currmap = g_map;
while(currmap)
{
if(strcmp(name, currmap->name) == 0)
{
break;
}
currmap = currmap->next;
}
return currmap;
}
unsigned char *load_file(const char *file, unsigned int *size)
{
FILE *fp;
unsigned char *data = NULL;
do
{
fp = fopen(file, "rb");
if(fp != NULL)
{
(void) fseek(fp, 0, SEEK_END);
*size = ftell(fp);
rewind(fp);
if(*size < sizeof(Elf32_Ehdr))
{
fprintf(stderr, "Error, invalid file size\n");
break;
}
data = (unsigned char *) malloc(*size);
if(data == NULL)
{
fprintf(stderr, "Error, could not allocate memory for ELF\n");
break;
}
(void) fread(data, 1, *size, fp);
fclose(fp);
}
else
{
fprintf(stderr, "Error, could not find file %s\n", file);
}
}
while(0);
return data;
}
/* Validate the ELF header */
int validate_header(unsigned char *data)
{
Elf32_Ehdr *head;
int ret = 0;
head = (Elf32_Ehdr*) data;
do
{
/* Read in the header structure */
g_elfhead.iMagic = LW(head->e_magic);
g_elfhead.iClass = head->e_class;
g_elfhead.iData = head->e_data;
g_elfhead.iIdver = head->e_idver;
g_elfhead.iType = LH(head->e_type);
g_elfhead.iMachine = LH(head->e_machine);
g_elfhead.iVersion = LW(head->e_version);
g_elfhead.iEntry = LW(head->e_entry);
g_elfhead.iPhoff = LW(head->e_phoff);
g_elfhead.iShoff = LW(head->e_shoff);
g_elfhead.iFlags = LW(head->e_flags);
g_elfhead.iEhsize = LH(head->e_ehsize);
g_elfhead.iPhentsize = LH(head->e_phentsize);
g_elfhead.iPhnum = LH(head->e_phnum);
g_elfhead.iShentsize = LH(head->e_shentsize);
g_elfhead.iShnum = LH(head->e_shnum);
g_elfhead.iShstrndx = LH(head->e_shstrndx);
if(g_verbose)
{
fprintf(stderr, "Magic %08X, Class %02X, Data %02X, Idver %02X\n", g_elfhead.iMagic,
g_elfhead.iClass, g_elfhead.iData, g_elfhead.iIdver);
fprintf(stderr, "Type %04X, Machine %04X, Version %08X, Entry %08X\n", g_elfhead.iType,
g_elfhead.iMachine, g_elfhead.iVersion, g_elfhead.iEntry);
fprintf(stderr, "Phoff %08X, Shoff %08X, Flags %08X, Ehsize %08X\n", g_elfhead.iPhoff,
g_elfhead.iShoff, g_elfhead.iFlags, g_elfhead.iEhsize);
fprintf(stderr, "Phentsize %04X, Phnum %04X\n", g_elfhead.iPhentsize, g_elfhead.iPhnum);
fprintf(stderr, "Shentsize %04X, Shnum %08X, Shstrndx %04X\n", g_elfhead.iShentsize,
g_elfhead.iShnum, g_elfhead.iShstrndx);
}
if(g_elfhead.iMagic != ELF_MAGIC)
{
fprintf(stderr, "Error, invalid magic in the header\n");
break;
}
if((g_elfhead.iType != ELF_EXEC_TYPE) && (g_elfhead.iType != ELF_PRX_TYPE))
{
fprintf(stderr, "Error, not EXEC type elf\n");
break;
}
if(g_elfhead.iMachine != ELF_MACHINE_MIPS)
{
fprintf(stderr, "Error, not MIPS type ELF\n");
break;
}
if(g_elfhead.iShnum < g_elfhead.iShstrndx)
{
fprintf(stderr, "Error, number of headers is less than section string index\n");
break;
}
ret = 1;
}
while(0);
return ret;
}
/* Load sections into ram */
int load_sections(unsigned char *data)
{
int ret = 0;
int found_rel = 0;
unsigned int load_addr = 0xFFFFFFFF;
if(g_elfhead.iShnum > 0)
{
do
{
Elf32_Shdr *sect;
int i;
g_elfsections = (struct ElfSection *) malloc(sizeof(struct ElfSection) * g_elfhead.iShnum);
if(g_elfsections == NULL)
{
fprintf(stderr, "Error, could not allocate memory for sections\n");
break;
}
memset(g_elfsections, 0, sizeof(struct ElfSection) * g_elfhead.iShnum);
for(i = 0; i < g_elfhead.iShnum; i++)
{
sect = (Elf32_Shdr *) (g_elfdata + g_elfhead.iShoff + (i * g_elfhead.iShentsize));
g_elfsections[i].iName = LW(sect->sh_name);
g_elfsections[i].iType = LW(sect->sh_type);
g_elfsections[i].iAddr = LW(sect->sh_addr);
g_elfsections[i].iFlags = LW(sect->sh_flags);
g_elfsections[i].iOffset = LW(sect->sh_offset);
g_elfsections[i].iSize = LW(sect->sh_size);
g_elfsections[i].iLink = LW(sect->sh_link);
g_elfsections[i].iInfo = LW(sect->sh_info);
g_elfsections[i].iAddralign = LW(sect->sh_addralign);
g_elfsections[i].iEntsize = LW(sect->sh_entsize);
g_elfsections[i].iIndex = i;
if(g_elfsections[i].iOffset != 0)
{
g_elfsections[i].pData = g_elfdata + g_elfsections[i].iOffset;
}
if(g_elfsections[i].iFlags & SHF_ALLOC)
{
g_elfsections[i].blOutput = 1;
if(g_elfsections[i].iAddr < load_addr)
{
load_addr = g_elfsections[i].iAddr;
}
}
if(((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC))
&& (g_elfsections[g_elfsections[i].iInfo].iFlags & SHF_ALLOC))
{
g_elfsections[i].pRef = &g_elfsections[g_elfsections[i].iInfo];
found_rel = 1;
}
}
/* Okay so we have loaded all the sections, lets fix up the names */
for(i = 0; i < g_elfhead.iShnum; i++)
{
strcpy(g_elfsections[i].szName, (char *) (g_elfsections[g_elfhead.iShstrndx].pData + g_elfsections[i].iName));
if(strcmp(g_elfsections[i].szName, PSP_MODULE_INFO_NAME) == 0)
{
g_modinfo = &g_elfsections[i];
}
else if(strcmp(g_elfsections[i].szName, PRX_LIBSTUB_SECT) == 0)
{
g_libstub = &g_elfsections[i];
}
else if(strcmp(g_elfsections[i].szName, PRX_STUBTEXT_SECT) == 0)
{
g_stubtext = &g_elfsections[i];
}
else if(strcmp(g_elfsections[i].szName, PRX_NID_SECT) == 0)
{
g_nid = &g_elfsections[i];
}
}
if(g_verbose)
{
for(i = 0; i < g_elfhead.iShnum; i++)
{
fprintf(stderr, "\nSection %d: %s\n", i, g_elfsections[i].szName);
fprintf(stderr, "Name %08X, Type %08X, Flags %08X, Addr %08X\n",
g_elfsections[i].iName, g_elfsections[i].iType,
g_elfsections[i].iFlags, g_elfsections[i].iAddr);
fprintf(stderr, "Offset %08X, Size %08X, Link %08X, Info %08X\n",
g_elfsections[i].iOffset, g_elfsections[i].iSize,
g_elfsections[i].iLink, g_elfsections[i].iInfo);
fprintf(stderr, "Addralign %08X, Entsize %08X pData %p\n",
g_elfsections[i].iAddralign, g_elfsections[i].iEntsize,
g_elfsections[i].pData);
}
fprintf(stderr, "ELF Load Base address %08X\n", load_addr);
}
if(g_modinfo == NULL)
{
fprintf(stderr, "Error, no sceModuleInfo section found\n");
break;
}
if(g_libstub == NULL)
{
fprintf(stderr, "Error, no .lib.stub section found\n");
break;
}
if(g_stubtext == NULL)
{
fprintf(stderr, "Error, no stub text section found\n");
break;
}
if(g_nid == NULL)
{
fprintf(stderr, "Error, no nid section found\n");
break;
}
ret = 1;
}
while(0);
}
else
{
fprintf(stderr, "Error, no sections in the ELF\n");
}
return ret;
}
/* Load an ELF file */
int load_elf(const char *elf)
{
int ret = 0;
do
{
g_elfdata = load_file(elf, &g_elfsize);
if(g_elfdata == NULL)
{
break;
}
if(!validate_header(g_elfdata))
{
break;
}
if(!load_sections(g_elfdata))
{
break;
}
ret = 1;
}
while(0);
return ret;
}
/* Free allocated memory */
void free_data(void)
{
if(g_elfdata != NULL)
{
free(g_elfdata);
g_elfdata = NULL;
}
if(g_elfsections != NULL)
{
free(g_elfsections);
g_elfsections = NULL;
}
}
void strip_wsp(char *str)
{
int len;
char *p;
len = strlen(str);
while((len > 0) && (isspace(str[len-1])))
{
str[--len] = 0;
}
p = str;
while(isspace(*p))
{
p++;
len--;
}
memmove(str, p, len);
str[len] = 0;
}
/* Load map file in
* File format is :-
* @LibraryName followed by 0 or more
* OLDNID=NEWNID [ Comment ]
*
* Read in badly :P
*/
int load_mapfile(const char *mapfile)
{
int ret = 1;
char buf[1024];
struct ImportMap *currmap = NULL;
int line = 0;
if(mapfile != NULL)
{
do
{
FILE *fp;
fp = fopen(mapfile, "r");
if(fp != NULL)
{
while(fgets(buf, sizeof(buf), fp))
{
line++;
strip_wsp(buf);
if((buf[0]) && (buf[0] != '#'))
{
if(buf[0] == '@')
{
struct ImportMap *temp;
temp = (struct ImportMap *) malloc(sizeof(struct ImportMap));
if(temp == NULL)
{
printf("Error allocating memory for import map\n");
ret = 0;
break;
}
memset(temp, 0, sizeof(struct ImportMap));
if(currmap == NULL)
{
g_map = temp;
}
else
{
temp->next = currmap;
g_map = temp;
}
currmap = temp;
if(buf[1])
{
strncpy(currmap->name, &buf[1], 32);
currmap->name[31] = 0;
}
else
{
printf("Invalid library name at line %d\n", line);
break;
}
if(g_verbose)
{
printf("Mapping library %s\n", currmap->name);
}
}
else
{
unsigned int oldnid;
unsigned int newnid;
char *endp;
if(currmap->count == MAX_MAPNIDS)
{
printf("Error, number of defined nids exceed maximum\n");
break;
}
/* Hex data should be prefixed with 0 */
if(buf[0] == '0')
{
errno = 0;
oldnid = strtoul(buf, &endp, 16);
if((errno != 0) || (*endp != ':'))
{
printf("Invalid NID entry on line %d\n", line);
continue;
}
}
else
{
unsigned char hash[SHA1_DIGEST_SIZE];
endp = strchr(buf, ':');
if(endp == NULL)
{
printf("Invalid NID entry on line %d\n", line);
continue;
}
sha1(hash, (unsigned char *) buf, endp-buf);
oldnid = hash[0] | (hash[1] << 8) | (hash[2] << 16) | (hash[3] << 24);
}
newnid = strtoul(endp+1, &endp, 16);
if(g_verbose)
{
fprintf(stderr, "NID Mapping 0x%08X to 0x%08X\n", oldnid, newnid);
}
currmap->nids[currmap->count].oldnid = oldnid;
currmap->nids[currmap->count].newnid = newnid;
currmap->count++;
}
}
}
fclose(fp);
}
}
while(0);
}
return ret;
}
#define MIPS_JR_31 0x03e00008
#define MIPS_NOP 0x0
int fixup_imports(void)
{
unsigned int *pText;
unsigned int *pNid;
struct PspModuleImport *pLastImport = NULL;
int count;
/* First let's check the sizes are correct */
if(g_stubtext->iSize != (g_nid->iSize * 2))
{
fprintf(stderr, "Error, size of text section and nid section do not match\n");
return 0;
}
count = g_nid->iSize / 4;
pText = (unsigned int *) g_stubtext->pData;
pNid = (unsigned int *) g_nid->pData;
if(g_verbose)
{
fprintf(stderr, "Import count %d\n", count);
}
while(count > 0)
{
unsigned int stub_addr;
unsigned int stub_nid;
unsigned int sect_nid;
stub_addr = LW(pText[0]);
stub_nid = LW(pText[1]);
sect_nid = LW(pNid[0]);
/* Check if this is an original format NID */
if((stub_addr != MIPS_JR_31) || (stub_nid != MIPS_NOP))
{
struct PspModuleImport *pImport;
u16 func_count;
if(g_verbose)
{
fprintf(stderr, "Found import to fixup. pStub %08X, Nid %08X, NidInSect %08X\n", stub_addr, stub_nid, sect_nid);
}
if(stub_nid != sect_nid)
{
fprintf(stderr, "Error, unmatched NIDs\n");
return 0;
}
if((stub_addr < g_libstub->iAddr) || (stub_addr > (g_libstub->iAddr + g_libstub->iSize)) || (stub_addr & 3))
{
fprintf(stderr, "Error, invalid stub address\n");
return 0;
}
pImport = (struct PspModuleImport *) (g_libstub->pData + (stub_addr - g_libstub->iAddr));
if(g_verbose)
{
fprintf(stderr, "Import Stub %p, %08X, %08X, %02X, %02X, %04X, %08X, %08X\n", pImport,
LW(pImport->name), LW(pImport->flags), pImport->entry_size, pImport->var_count,
LH(pImport->func_count), LW(pImport->nids), LW(pImport->funcs));
}
func_count = LH(pImport->func_count);
if(func_count == 0)
{
/* Setup the stub */
SW(&pImport->nids, ((unsigned char *) pNid - g_nid->pData) + g_nid->iAddr);
SW(&pImport->funcs, ((unsigned char *) pText - g_stubtext->pData) + g_stubtext->iAddr);
}
else
{
if((pLastImport) && (pImport != pLastImport))
{
fprintf(stderr, "Error, could not fixup imports, stubs out of order.\n");
fprintf(stderr, "Ensure the SDK libraries are linked in last to correct this error\n");
return 0;
}
}
pLastImport = pImport;
func_count++;
SH(&pImport->func_count, func_count);
SW(&pText[0], MIPS_JR_31);
SW(&pText[1], MIPS_NOP);
}
else
{
/* Set last import to some value so we know if we have out of order stubs over a fixed stub table */
pLastImport = (struct PspModuleImport *) pText;
}
pText += 2;
pNid++;
count--;
}
/* Should indicate no error occurred */
if(count == 0)
{
if(g_verbose)
{
fprintf(stderr, "No libraries to fixup\n");
}
}
return 1;
}
int fixup_nidmap(void)
{
struct PspModuleImport *pImport;
int size;
pImport = (struct PspModuleImport *) g_libstub->pData;
size = g_libstub->iSize;
while(size >= sizeof(struct PspModuleImport))
{
const char *str;
str = (const char*) find_data(LW(pImport->name));
if(str)
{
struct ImportMap *pMap;
pMap = find_map_by_name(str);
if(pMap)
{
int count;
unsigned int *pNid;
pNid = (unsigned int*) find_data(LW(pImport->nids));
count = LH(pImport->func_count) + pImport->var_count;
if(pNid && (count > 0))
{
if(g_verbose)
{
fprintf(stderr, "Mapping library %s\n", str);
}
while(count > 0)
{
int i;
for(i = 0; i < pMap->count; i++)
{
unsigned oldnid, newnid;
if(g_reversemap)
{
oldnid = pMap->nids[i].newnid;
newnid = pMap->nids[i].oldnid;
}
else
{
newnid = pMap->nids[i].newnid;
oldnid = pMap->nids[i].oldnid;
}
if(oldnid == *pNid)
{
if(g_verbose)
{
fprintf(stderr, "Mapping 0x%08X to 0x%08X\n", oldnid, newnid);
}
*pNid = newnid;
break;
}
}
pNid++;
count--;
}
}
}
}
pImport++;
size -= sizeof(struct PspModuleImport);
}
return 1;
}
int main(int argc, char **argv)
{
int ret = 0;
if(process_args(argc, argv))
{
if(load_mapfile(g_mapfile) && load_elf(g_infile))
{
if(fixup_imports() && fixup_nidmap())
{
FILE *fp;
fp = fopen(g_outfile, "wb");
if(fp != NULL)
{
(void) fwrite(g_elfdata, 1, g_elfsize, fp);
fclose(fp);
}
else
{
fprintf(stderr, "Error, couldn't open %s for writing\n", g_outfile);
return 0;
}
}
else
{
ret = 1;
}
free_data();
}
else
{
ret = 1;
}
}
else
{
print_help();
ret = 1;
}
return ret;
}

941
tools/psp-prxgen.c Normal file
View File

@@ -0,0 +1,941 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* psp-prxgen.c - Simple program to build a PRX file (and strip at the same time)
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: psp-prxgen.c 1520 2005-12-04 20:09:36Z tyranid $
*/
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <ctype.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "types.h"
#include "elftypes.h"
#include "prxtypes.h"
/* Arrangement of ELF file after stripping
*
* ELF Header - 52 bytes
* Program Headers
* .text data
* .data data
* Section Headers
* Relocation data
* Section Header String Table
*
* When stripping the sections remove anything which isn't an allocated section or a relocation section.
* The section string section we will rebuild.
*/
static const char *g_outfile;
static const char *g_infile;
static unsigned char *g_elfdata = NULL;
static struct ElfHeader g_elfhead = {0};
static struct ElfSection *g_elfsections = NULL;
static struct ElfSection *g_modinfo = NULL;
static int g_out_sects = 2;
static int g_alloc_size = 0;
static int g_mem_size = 0;
static int g_reloc_size = 0;
static int g_str_size = 1;
/* Base addresses in the Elf */
static int g_phbase = 0;
static int g_allocbase = 0;
static int g_shbase = 0;
static int g_relocbase = 0;
static int g_shstrbase = 0;
/* Specifies that the current usage is to the print the pspsdk path */
static int g_verbose = 0;
static struct option arg_opts[] =
{
{"verbose", no_argument, NULL, 'v'},
{ NULL, 0, NULL, 0 }
};
/* Process the arguments */
int process_args(int argc, char **argv)
{
int ch;
g_outfile = NULL;
g_infile = NULL;
ch = getopt_long(argc, argv, "v", arg_opts, NULL);
while(ch != -1)
{
switch(ch)
{
case 'v' : g_verbose = 1;
break;
default : break;
};
ch = getopt_long(argc, argv, "v", arg_opts, NULL);
}
argc -= optind;
argv += optind;
if(argc < 2)
{
return 0;
}
g_infile = argv[0];
g_outfile = argv[1];
if(g_verbose)
{
fprintf(stderr, "Loading %s, outputting to %s\n", g_infile, g_outfile);
}
return 1;
}
void print_help(void)
{
fprintf(stderr, "Usage: psp-prxgen [-v] infile.elf outfile.prx\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, "-v, --verbose : Verbose output\n");
}
unsigned char *load_file(const char *file)
{
FILE *fp;
unsigned int size;
unsigned char *data = NULL;
do
{
fp = fopen(file, "rb");
if(fp != NULL)
{
(void) fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
if(size < sizeof(Elf32_Ehdr))
{
fprintf(stderr, "Error, invalid file size\n");
break;
}
data = (unsigned char *) malloc(size);
if(data == NULL)
{
fprintf(stderr, "Error, could not allocate memory for ELF\n");
break;
}
(void) fread(data, 1, size, fp);
fclose(fp);
}
else
{
fprintf(stderr, "Error, could not find file %s\n", file);
}
}
while(0);
return data;
}
/* Validate the ELF header */
int validate_header(unsigned char *data)
{
Elf32_Ehdr *head;
int ret = 0;
head = (Elf32_Ehdr*) data;
do
{
/* Read in the header structure */
g_elfhead.iMagic = LW(head->e_magic);
g_elfhead.iClass = head->e_class;
g_elfhead.iData = head->e_data;
g_elfhead.iIdver = head->e_idver;
g_elfhead.iType = LH(head->e_type);
g_elfhead.iMachine = LH(head->e_machine);
g_elfhead.iVersion = LW(head->e_version);
g_elfhead.iEntry = LW(head->e_entry);
g_elfhead.iPhoff = LW(head->e_phoff);
g_elfhead.iShoff = LW(head->e_shoff);
g_elfhead.iFlags = LW(head->e_flags);
g_elfhead.iEhsize = LH(head->e_ehsize);
g_elfhead.iPhentsize = LH(head->e_phentsize);
g_elfhead.iPhnum = LH(head->e_phnum);
g_elfhead.iShentsize = LH(head->e_shentsize);
g_elfhead.iShnum = LH(head->e_shnum);
g_elfhead.iShstrndx = LH(head->e_shstrndx);
if(g_verbose)
{
fprintf(stderr, "Magic %08X, Class %02X, Data %02X, Idver %02X\n", g_elfhead.iMagic,
g_elfhead.iClass, g_elfhead.iData, g_elfhead.iIdver);
fprintf(stderr, "Type %04X, Machine %04X, Version %08X, Entry %08X\n", g_elfhead.iType,
g_elfhead.iMachine, g_elfhead.iVersion, g_elfhead.iEntry);
fprintf(stderr, "Phoff %08X, Shoff %08X, Flags %08X, Ehsize %08X\n", g_elfhead.iPhoff,
g_elfhead.iShoff, g_elfhead.iFlags, g_elfhead.iEhsize);
fprintf(stderr, "Phentsize %04X, Phnum %04X\n", g_elfhead.iPhentsize, g_elfhead.iPhnum);
fprintf(stderr, "Shentsize %04X, Shnum %08X, Shstrndx %04X\n", g_elfhead.iShentsize,
g_elfhead.iShnum, g_elfhead.iShstrndx);
}
if(g_elfhead.iMagic != ELF_MAGIC)
{
fprintf(stderr, "Error, invalid magic in the header\n");
break;
}
if((g_elfhead.iType != ELF_EXEC_TYPE) && (g_elfhead.iType != ELF_PRX_TYPE))
{
fprintf(stderr, "Error, not EXEC type elf\n");
break;
}
if(g_elfhead.iMachine != ELF_MACHINE_MIPS)
{
fprintf(stderr, "Error, not MIPS type ELF\n");
break;
}
if(g_elfhead.iShnum < g_elfhead.iShstrndx)
{
fprintf(stderr, "Error, number of headers is less than section string index\n");
break;
}
ret = 1;
}
while(0);
return ret;
}
/* Load sections into ram */
int load_sections(unsigned char *data)
{
int ret = 0;
int found_rel = 0;
unsigned int load_addr = 0xFFFFFFFF;
if(g_elfhead.iShnum > 0)
{
do
{
Elf32_Shdr *sect;
int i;
g_elfsections = (struct ElfSection *) malloc(sizeof(struct ElfSection) * g_elfhead.iShnum);
if(g_elfsections == NULL)
{
fprintf(stderr, "Error, could not allocate memory for sections\n");
break;
}
memset(g_elfsections, 0, sizeof(struct ElfSection) * g_elfhead.iShnum);
for(i = 0; i < g_elfhead.iShnum; i++)
{
sect = (Elf32_Shdr *) (g_elfdata + g_elfhead.iShoff + (i * g_elfhead.iShentsize));
g_elfsections[i].iName = LW(sect->sh_name);
g_elfsections[i].iType = LW(sect->sh_type);
g_elfsections[i].iAddr = LW(sect->sh_addr);
g_elfsections[i].iFlags = LW(sect->sh_flags);
g_elfsections[i].iOffset = LW(sect->sh_offset);
g_elfsections[i].iSize = LW(sect->sh_size);
g_elfsections[i].iLink = LW(sect->sh_link);
g_elfsections[i].iInfo = LW(sect->sh_info);
g_elfsections[i].iAddralign = LW(sect->sh_addralign);
g_elfsections[i].iEntsize = LW(sect->sh_entsize);
g_elfsections[i].iIndex = i;
if(g_elfsections[i].iOffset != 0)
{
g_elfsections[i].pData = g_elfdata + g_elfsections[i].iOffset;
}
if(g_elfsections[i].iFlags & SHF_ALLOC)
{
g_elfsections[i].blOutput = 1;
if(g_elfsections[i].iAddr < load_addr)
{
load_addr = g_elfsections[i].iAddr;
}
}
if(((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC))
&& (g_elfsections[g_elfsections[i].iInfo].iFlags & SHF_ALLOC))
{
g_elfsections[i].pRef = &g_elfsections[g_elfsections[i].iInfo];
found_rel = 1;
g_elfsections[i].blOutput = 1;
}
}
/* Okay so we have loaded all the sections, lets fix up the names */
for(i = 0; i < g_elfhead.iShnum; i++)
{
strcpy(g_elfsections[i].szName, (char *) (g_elfsections[g_elfhead.iShstrndx].pData + g_elfsections[i].iName));
if(strcmp(g_elfsections[i].szName, PSP_MODULE_INFO_NAME) == 0)
{
g_modinfo = &g_elfsections[i];
}
else if(strcmp(g_elfsections[i].szName, PSP_MODULE_REMOVE_REL) == 0)
{
/* Don't output .rel.lib.stub relocations */
g_elfsections[i].blOutput = 0;
}
}
if(g_verbose)
{
for(i = 0; i < g_elfhead.iShnum; i++)
{
fprintf(stderr, "\nSection %d: %s\n", i, g_elfsections[i].szName);
fprintf(stderr, "Name %08X, Type %08X, Flags %08X, Addr %08X\n",
g_elfsections[i].iName, g_elfsections[i].iType,
g_elfsections[i].iFlags, g_elfsections[i].iAddr);
fprintf(stderr, "Offset %08X, Size %08X, Link %08X, Info %08X\n",
g_elfsections[i].iOffset, g_elfsections[i].iSize,
g_elfsections[i].iLink, g_elfsections[i].iInfo);
fprintf(stderr, "Addralign %08X, Entsize %08X pData %p\n",
g_elfsections[i].iAddralign, g_elfsections[i].iEntsize,
g_elfsections[i].pData);
}
fprintf(stderr, "ELF Load Base address %08X\n", load_addr);
}
if(g_modinfo == NULL)
{
fprintf(stderr, "Error, no sceModuleInfo section found\n");
break;
}
if(!found_rel)
{
fprintf(stderr, "Error, found no relocation sections\n");
break;
}
if(load_addr != 0)
{
fprintf(stderr, "Error, ELF not loaded to address 0 (%08X)\n", load_addr);
break;
}
ret = 1;
}
while(0);
}
else
{
fprintf(stderr, "Error, no sections in the ELF\n");
}
return ret;
}
int remove_weak_relocs(struct ElfSection *pReloc, struct ElfSection *pSymbol, struct ElfSection *pString)
{
int iCount;
int iMaxSymbol;
void *pNewRel = NULL;
Elf32_Rel *pInRel;
Elf32_Rel *pOutRel;
Elf32_Sym *pSymData = (Elf32_Sym *) pSymbol->pData;
char *pStrData = NULL;
int iOutput;
int i;
if(pString != NULL)
{
pStrData = (char *) pString->pData;
}
iMaxSymbol = pSymbol->iSize / sizeof(Elf32_Sym);
iCount = pReloc->iSize / sizeof(Elf32_Rel);
pNewRel = malloc(pReloc->iSize);
if(pNewRel == NULL)
{
return 0;
}
pOutRel = (Elf32_Rel *) pNewRel;
pInRel = (Elf32_Rel *) pReloc->pData;
iOutput = 0;
if(g_verbose)
{
fprintf(stderr, "[%s] Processing %d relocations, %d symbols\n", pReloc->szName, iCount, iMaxSymbol);
}
for(i = 0; i < iCount; i++)
{
int iSymbol;
iSymbol = ELF32_R_SYM(LW(pInRel->r_info));
if(g_verbose)
{
fprintf(stderr, "Relocation %d - Symbol %x\n", iOutput, iSymbol);
}
if(iSymbol >= iMaxSymbol)
{
fprintf(stderr, "Warning: Ignoring relocation as cannot find matching symbol\n");
}
else
{
if(g_verbose)
{
if(pStrData != NULL)
{
fprintf(stderr, "Symbol %d - Name %s info %x ndx %x\n", iSymbol, &pStrData[pSymData[iSymbol].st_name],
pSymData[iSymbol].st_info, pSymData[iSymbol].st_shndx);
}
else
{
fprintf(stderr, "Symbol %d - Name %d info %x ndx %x\n", iSymbol, pSymData[iSymbol].st_name,
pSymData[iSymbol].st_info, pSymData[iSymbol].st_shndx);
}
}
if(LH(pSymData[iSymbol].st_shndx) == 0)
{
if(g_verbose)
{
fprintf(stderr, "Deleting relocation\n");
}
}
else
{
/* We are keeping this relocation, copy it across */
*pOutRel = *pInRel;
pOutRel++;
iOutput++;
}
}
pInRel++;
}
/* If we deleted some relocations */
if(iOutput < iCount)
{
int iSize;
iSize = iOutput * sizeof(Elf32_Rel);
if(g_verbose)
{
fprintf(stderr, "Old relocation size %d, new %d\n", pReloc->iSize, iSize);
}
pReloc->iSize = iSize;
/* If size is zero then delete this section */
if(iSize == 0)
{
pReloc->blOutput = 0;
}
else
{
/* Copy across the new relocation data */
memcpy(pReloc->pData, pNewRel, pReloc->iSize);
}
}
free(pNewRel);
return 1;
}
/* Let's remove the weak relocations from the list */
int process_relocs(void)
{
int i;
for(i = 0; i < g_elfhead.iShnum; i++)
{
if((g_elfsections[i].blOutput) && (g_elfsections[i].iType == SHT_REL))
{
struct ElfSection *pReloc;
pReloc = &g_elfsections[i];
if((pReloc->iLink < g_elfhead.iShnum) && (g_elfsections[pReloc->iLink].iType == SHT_SYMTAB))
{
struct ElfSection *pStrings = NULL;
struct ElfSection *pSymbols;
pSymbols = &g_elfsections[pReloc->iLink];
if((pSymbols->iLink < g_elfhead.iShnum) && (g_elfsections[pSymbols->iLink].iType == SHT_STRTAB))
{
pStrings = &g_elfsections[pSymbols->iLink];
}
if(!remove_weak_relocs(pReloc, pSymbols, pStrings))
{
return 0;
}
}
else
{
if(g_verbose)
{
fprintf(stderr, "Ignoring relocation section %d, invalid link number\n", i);
}
}
}
}
return 1;
}
/* Reindex the sections we are keeping */
void reindex_sections(void)
{
int i;
int sect = 1;
for(i = 0; i < g_elfhead.iShnum; i++)
{
if(g_elfsections[i].blOutput)
{
g_elfsections[i].iIndex = sect++;
}
}
}
/* Load an ELF file */
int load_elf(const char *elf)
{
int ret = 0;
do
{
g_elfdata = load_file(elf);
if(g_elfdata == NULL)
{
break;
}
if(!validate_header(g_elfdata))
{
break;
}
if(!load_sections(g_elfdata))
{
break;
}
if(!process_relocs())
{
break;
}
reindex_sections();
ret = 1;
}
while(0);
return ret;
}
int calculate_outsize(void)
{
/* out_sects starts at two for the null section and the section string table */
int out_sects = 2;
int alloc_size = 0;
int reloc_size = 0;
int mem_size = 0;
/* 1 for the NUL for the NULL section */
int str_size = 1;
int i;
/* Calculate how big our output file needs to be */
/* We have elf header + 1 PH + allocated data + section headers + relocation data */
/* Note that the ELF should be based from 0, we use this to calculate the alloc and mem sizes */
/* Skip null section */
for(i = 1; i < g_elfhead.iShnum; i++)
{
if(g_elfsections[i].blOutput)
{
if(g_elfsections[i].iType == SHT_PROGBITS)
{
unsigned int top_addr;
top_addr = g_elfsections[i].iAddr + g_elfsections[i].iSize;
if(top_addr > alloc_size)
{
alloc_size = top_addr;
}
if(top_addr > mem_size)
{
mem_size = top_addr;
}
out_sects++;
str_size += strlen(g_elfsections[i].szName) + 1;
}
else if((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC))
{
/* Check this is a reloc for an allocated section */
if(g_elfsections[g_elfsections[i].iInfo].iFlags & SHF_ALLOC)
{
reloc_size += g_elfsections[i].iSize;
out_sects++;
str_size += strlen(g_elfsections[i].szName) + 1;
}
}
else
{
unsigned int top_addr;
top_addr = g_elfsections[i].iAddr + g_elfsections[i].iSize;
if(top_addr > mem_size)
{
mem_size = top_addr;
}
out_sects++;
str_size += strlen(g_elfsections[i].szName) + 1;
}
}
}
alloc_size = (alloc_size + 3) & ~3;
mem_size = (mem_size + 3) & ~3;
str_size = (str_size + 3) & ~3;
str_size += strlen(ELF_SH_STRTAB) + 1;
if(g_verbose)
{
fprintf(stderr, "Out_sects %d, alloc_size %d, reloc_size %d, str_size %d, mem_size %d\n",
out_sects, alloc_size, reloc_size, str_size, mem_size);
}
/* Save them for future use */
g_out_sects = out_sects;
g_alloc_size = alloc_size;
g_reloc_size = reloc_size;
g_mem_size = mem_size;
g_str_size = str_size;
/* Lets build the offsets */
g_phbase = sizeof(Elf32_Ehdr);
/* The allocated data needs to be 16 byte aligned */
g_allocbase = (g_phbase + sizeof(Elf32_Shdr) + 0xF) & ~0xF;
g_shbase = g_allocbase + g_alloc_size;
g_relocbase = g_shbase + (g_out_sects * sizeof(Elf32_Shdr));
g_shstrbase = g_relocbase + g_reloc_size;
if(g_verbose)
{
fprintf(stderr, "PHBase %08X, AllocBase %08X, SHBase %08X\n", g_phbase, g_allocbase, g_shbase);
fprintf(stderr, "Relocbase %08X, Shstrbase %08X\n", g_relocbase, g_shstrbase);
fprintf(stderr, "Total size %d\n", g_shstrbase + g_str_size);
}
return (g_shstrbase + g_str_size);
}
/* Output the ELF header */
void output_header(unsigned char *data)
{
Elf32_Ehdr *head;
head = (Elf32_Ehdr*) data;
SW(&head->e_magic, g_elfhead.iMagic);
head->e_class = g_elfhead.iClass;
head->e_data = g_elfhead.iData;
head->e_idver = g_elfhead.iIdver;
SH(&head->e_type, ELF_PRX_TYPE);
SH(&head->e_machine, g_elfhead.iMachine);
SW(&head->e_version, g_elfhead.iVersion);
SW(&head->e_entry, g_elfhead.iEntry);
SW(&head->e_phoff, g_phbase);
SW(&head->e_shoff, g_shbase);
SW(&head->e_flags, g_elfhead.iFlags);
SH(&head->e_ehsize, sizeof(Elf32_Ehdr));
SH(&head->e_phentsize, sizeof(Elf32_Phdr));
SH(&head->e_phnum, 1);
SH(&head->e_shentsize, sizeof(Elf32_Shdr));
SH(&head->e_shnum, g_out_sects);
SH(&head->e_shstrndx, g_out_sects-1);
}
/* Output the program header */
void output_ph(unsigned char *data)
{
Elf32_Phdr *phdr;
struct PspModuleInfo *pModinfo;
int mod_flags;
phdr = (Elf32_Phdr*) data;
pModinfo = (struct PspModuleInfo *) (g_modinfo->pData);
mod_flags = LW(pModinfo->flags);
SW(&phdr->p_type, 1);
/* Starts after the program header */
SW(&phdr->p_offset, g_allocbase);
SW(&phdr->p_vaddr, 0);
/* Check if this is a kernel module */
if(mod_flags & 0x1000)
{
SW(&phdr->p_paddr, 0x80000000 | (g_modinfo->iAddr + g_allocbase));
}
else
{
SW(&phdr->p_paddr, (g_modinfo->iAddr + g_allocbase));
}
SW(&phdr->p_filesz, g_alloc_size);
SW(&phdr->p_memsz, g_mem_size);
SW(&phdr->p_flags, 5);
SW(&phdr->p_align, 0x10);
}
/* Output the allocated sections */
void output_alloc(unsigned char *data)
{
int i;
for(i = 0; i < g_elfhead.iShnum; i++)
{
if((g_elfsections[i].blOutput) && (g_elfsections[i].iType == SHT_PROGBITS))
{
memcpy(&data[g_elfsections[i].iAddr], g_elfsections[i].pData, g_elfsections[i].iSize);
}
}
}
/* Output the section headers */
void output_sh(unsigned char *data)
{
unsigned int reloc_ofs;
unsigned int str_ofs;
Elf32_Shdr *shdr;
int i;
shdr = (Elf32_Shdr*) data;
/* For the NULL section */
shdr++;
memset(data, 0, g_out_sects * sizeof(Elf32_Shdr));
reloc_ofs = g_relocbase;
str_ofs = 1;
for(i = 1; i < g_elfhead.iShnum; i++)
{
if(g_elfsections[i].blOutput)
{
SW(&shdr->sh_name, str_ofs);
str_ofs += strlen(g_elfsections[i].szName) + 1;
SW(&shdr->sh_flags, g_elfsections[i].iFlags);
SW(&shdr->sh_addr, g_elfsections[i].iAddr);
SW(&shdr->sh_size, g_elfsections[i].iSize);
SW(&shdr->sh_link, 0);
SW(&shdr->sh_addralign, g_elfsections[i].iAddralign);
SW(&shdr->sh_entsize, g_elfsections[i].iEntsize);
if((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC))
{
SW(&shdr->sh_type, SHT_PRXRELOC);
SW(&shdr->sh_info, g_elfsections[i].pRef->iIndex);
SW(&shdr->sh_offset, reloc_ofs);
reloc_ofs += g_elfsections[i].iSize;
}
else if(g_elfsections[i].iType == SHT_PROGBITS)
{
SW(&shdr->sh_type, g_elfsections[i].iType);
SW(&shdr->sh_info, 0);
SW(&shdr->sh_offset, g_allocbase + g_elfsections[i].iAddr);
}
else
{
SW(&shdr->sh_type, g_elfsections[i].iType);
SW(&shdr->sh_info, 0);
/* Point it to the end of the allocated section */
SW(&shdr->sh_offset, g_allocbase + g_alloc_size);
}
shdr++;
}
}
/* Fill in the shstrtab section */
SW(&shdr->sh_name, str_ofs);
SW(&shdr->sh_flags, 0);
SW(&shdr->sh_addr, 0);
SW(&shdr->sh_size, g_str_size);
SW(&shdr->sh_link, 0);
SW(&shdr->sh_addralign, 1);
SW(&shdr->sh_entsize, 0);
SW(&shdr->sh_type, SHT_STRTAB);
SW(&shdr->sh_info, 0);
SW(&shdr->sh_offset, g_shstrbase);
}
/* Output relocations */
void output_relocs(unsigned char *data)
{
int i;
unsigned char *pReloc;
pReloc = data;
for(i = 0; i < g_elfhead.iShnum; i++)
{
if((g_elfsections[i].blOutput) &&
((g_elfsections[i].iType == SHT_REL) || (g_elfsections[i].iType == SHT_PRXRELOC)))
{
Elf32_Rel *rel;
int j, count;
memcpy(pReloc, g_elfsections[i].pData, g_elfsections[i].iSize);
rel = (Elf32_Rel*) pReloc;
count = g_elfsections[i].iSize / sizeof(Elf32_Rel);
for(j = 0; j < count; j++)
{
unsigned int sym;
/* Clear the top 24bits of the info */
/* Kind of a dirty trick but hey :P */
sym = LW(rel->r_info);
sym &= 0xFF;
SW(&rel->r_info, sym);
rel++;
}
pReloc += g_elfsections[i].iSize;
}
}
}
/* Output the section header string table */
void output_shstrtab(unsigned char *data)
{
int i;
char *pData;
/* For the NULL section, memory should be zeroed anyway */
memset(data, 0, g_str_size);
pData = (char *) (data + 1);
for(i = 1; i < g_elfhead.iShnum; i++)
{
if(g_elfsections[i].blOutput)
{
if(g_verbose)
{
fprintf(stderr, "String %d: %s\n", i, g_elfsections[i].szName);
}
strcpy(pData, g_elfsections[i].szName);
pData += strlen(g_elfsections[i].szName) + 1;
}
}
strcpy(pData, ELF_SH_STRTAB);
}
/* Output a stripped prx file */
int output_prx(const char *prxfile)
{
int size;
unsigned char *data;
FILE *fp;
do
{
size = calculate_outsize();
data = (unsigned char *) malloc(size);
if(data == NULL)
{
fprintf(stderr, "Error, couldn't allocate output data\n");
break;
}
memset(data, 0, size);
output_header(data);
output_ph(data + g_phbase);
output_alloc(data + g_allocbase);
output_sh(data + g_shbase);
output_relocs(data + g_relocbase);
output_shstrtab(data + g_shstrbase);
fp = fopen(prxfile, "wb");
if(fp != NULL)
{
fwrite(data, 1, size, fp);
fclose(fp);
}
else
{
fprintf(stderr, "Error, could not open output file %s\n", prxfile);
}
free(data);
}
while(0);
return 0;
}
/* Free allocated memory */
void free_data(void)
{
if(g_elfdata != NULL)
{
free(g_elfdata);
g_elfdata = NULL;
}
if(g_elfsections != NULL)
{
free(g_elfsections);
g_elfsections = NULL;
}
}
int main(int argc, char **argv)
{
if(process_args(argc, argv))
{
if(load_elf(g_infile))
{
(void) output_prx(g_outfile);
free_data();
}
}
else
{
print_help();
}
return 0;
}

282
tools/sha1.c Normal file
View File

@@ -0,0 +1,282 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 18/06/2004
This is a byte oriented version of SHA1 that operates on arrays of bytes
stored in memory.
*/
#include <string.h> /* for memcpy() etc. */
#include <stdlib.h> /* for _lrotl with VC++ */
#include "sha1.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(__cplusplus)
extern "C"
{
#endif
/*
To obtain the highest speed on processors with 32-bit words, this code
needs to determine the order in which bytes are packed into such words.
The following block of code is an attempt to capture the most obvious
ways in which various environemnts specify their endian definitions.
It may well fail, in which case the definitions will need to be set by
editing at the points marked **** EDIT HERE IF NECESSARY **** below.
*/
/* PLATFORM SPECIFIC INCLUDES */
#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#ifdef WORDS_BIGENDIAN
#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
#else
#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
#endif
#ifdef _MSC_VER
#pragma intrinsic(memcpy)
#endif
#if 0 && defined(_MSC_VER)
#define rotl32 _lrotl
#define rotr32 _lrotr
#else
#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
#endif
#if !defined(bswap_32)
#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00))
#endif
#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN)
#define SWAP_BYTES
#else
#undef SWAP_BYTES
#endif
#if defined(SWAP_BYTES)
#define bsw_32(p,n) \
{ int _i = (n); while(_i--) ((sha1_32t*)p)[_i] = bswap_32(((sha1_32t*)p)[_i]); }
#else
#define bsw_32(p,n)
#endif
#define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
#if 0
#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define parity(x,y,z) ((x) ^ (y) ^ (z))
#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* Discovered by Rich Schroeppel and Colin Plumb */
#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
#define parity(x,y,z) ((x) ^ (y) ^ (z))
#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
#endif
/* Compile 64 bytes of hash data into SHA1 context. Note */
/* that this routine assumes that the byte order in the */
/* ctx->wbuf[] at this point is in such an order that low */
/* address bytes in the ORIGINAL byte stream will go in */
/* this buffer to the high end of 32-bit words on BOTH big */
/* and little endian systems */
#ifdef ARRAY
#define q(v,n) v[n]
#else
#define q(v,n) v##n
#endif
#define one_cycle(v,a,b,c,d,e,f,k,h) \
q(v,e) += rotr32(q(v,a),27) + \
f(q(v,b),q(v,c),q(v,d)) + k + h; \
q(v,b) = rotr32(q(v,b), 2)
#define five_cycle(v,f,k,i) \
one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \
one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \
one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \
one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \
one_cycle(v, 1,2,3,4,0, f,k,hf(i+4))
void sha1_compile(sha1_ctx ctx[1])
{ sha1_32t *w = ctx->wbuf;
#ifdef ARRAY
sha1_32t v[5];
memcpy(v, ctx->hash, 5 * sizeof(sha1_32t));
#else
sha1_32t v0, v1, v2, v3, v4;
v0 = ctx->hash[0]; v1 = ctx->hash[1];
v2 = ctx->hash[2]; v3 = ctx->hash[3];
v4 = ctx->hash[4];
#endif
#define hf(i) w[i]
five_cycle(v, ch, 0x5a827999, 0);
five_cycle(v, ch, 0x5a827999, 5);
five_cycle(v, ch, 0x5a827999, 10);
one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \
#undef hf
#define hf(i) (w[(i) & 15] = rotl32( \
w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \
^ w[((i) + 2) & 15] ^ w[(i) & 15], 1))
one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16));
one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17));
one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18));
one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19));
five_cycle(v, parity, 0x6ed9eba1, 20);
five_cycle(v, parity, 0x6ed9eba1, 25);
five_cycle(v, parity, 0x6ed9eba1, 30);
five_cycle(v, parity, 0x6ed9eba1, 35);
five_cycle(v, maj, 0x8f1bbcdc, 40);
five_cycle(v, maj, 0x8f1bbcdc, 45);
five_cycle(v, maj, 0x8f1bbcdc, 50);
five_cycle(v, maj, 0x8f1bbcdc, 55);
five_cycle(v, parity, 0xca62c1d6, 60);
five_cycle(v, parity, 0xca62c1d6, 65);
five_cycle(v, parity, 0xca62c1d6, 70);
five_cycle(v, parity, 0xca62c1d6, 75);
#ifdef ARRAY
ctx->hash[0] += v[0]; ctx->hash[1] += v[1];
ctx->hash[2] += v[2]; ctx->hash[3] += v[3];
ctx->hash[4] += v[4];
#else
ctx->hash[0] += v0; ctx->hash[1] += v1;
ctx->hash[2] += v2; ctx->hash[3] += v3;
ctx->hash[4] += v4;
#endif
}
void sha1_begin(sha1_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
ctx->hash[0] = 0x67452301;
ctx->hash[1] = 0xefcdab89;
ctx->hash[2] = 0x98badcfe;
ctx->hash[3] = 0x10325476;
ctx->hash[4] = 0xc3d2e1f0;
}
/* SHA1 hash data in an array of bytes into hash buffer and */
/* call the hash_compile function as required. */
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1])
{ sha1_32t pos = (sha1_32t)(ctx->count[0] & SHA1_MASK),
space = SHA1_BLOCK_SIZE - pos;
const unsigned char *sp = data;
if((ctx->count[0] += len) < len)
++(ctx->count[1]);
while(len >= space) /* tranfer whole blocks if possible */
{
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0;
bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2);
sha1_compile(ctx);
}
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
}
/* SHA1 final padding and digest calculation */
void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
{ sha1_32t i = (sha1_32t)(ctx->count[0] & SHA1_MASK);
/* put bytes in the buffer in an order in which references to */
/* 32-bit words will put bytes with lower addresses into the */
/* top of 32 bit words on BOTH big and little endian machines */
bsw_32(ctx->wbuf, (i + 3) >> 2);
/* we now need to mask valid bytes and add the padding which is */
/* a single 1 bit and as many zero bits as necessary. Note that */
/* we can always add the first padding byte here because the */
/* buffer always has at least one empty slot */
ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3);
ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3);
/* we need 9 or more empty positions, one for the padding byte */
/* (above) and eight for the length count. If there is not */
/* enough space, pad and empty the buffer */
if(i > SHA1_BLOCK_SIZE - 9)
{
if(i < 60) ctx->wbuf[15] = 0;
sha1_compile(ctx);
i = 0;
}
else /* compute a word index for the empty buffer positions */
i = (i >> 2) + 1;
while(i < 14) /* and zero pad all but last two positions */
ctx->wbuf[i++] = 0;
/* the following 32-bit length fields are assembled in the */
/* wrong byte order on little endian machines but this is */
/* corrected later since they are only ever used as 32-bit */
/* word values. */
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29);
ctx->wbuf[15] = ctx->count[0] << 3;
sha1_compile(ctx);
/* extract the hash value as bytes in case the hash buffer is */
/* misaligned for 32-bit words */
for(i = 0; i < SHA1_DIGEST_SIZE; ++i)
hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3)));
}
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha1_ctx cx[1];
sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx);
}
#if defined(__cplusplus)
}
#endif

84
tools/sha1.h Normal file
View File

@@ -0,0 +1,84 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 26/08/2003
*/
#ifndef _SHA1_H
#define _SHA1_H
#include <limits.h>
#define SHA1_BLOCK_SIZE 64
#define SHA1_DIGEST_SIZE 20
#if defined(__cplusplus)
extern "C"
{
#endif
/* define an unsigned 32-bit type */
#if defined(_MSC_VER)
typedef unsigned long sha1_32t;
#elif defined(ULONG_MAX) && ULONG_MAX == 0xfffffffful
typedef unsigned long sha1_32t;
#elif defined(UINT_MAX) && UINT_MAX == 0xffffffff
typedef unsigned int sha1_32t;
#else
# error Please define sha1_32t as an unsigned 32 bit type in sha1.h
#endif
/* type to hold the SHA256 context */
typedef struct
{ sha1_32t count[2];
sha1_32t hash[5];
sha1_32t wbuf[16];
} sha1_ctx;
/* Note that these prototypes are the same for both bit and */
/* byte oriented implementations. However the length fields */
/* are in bytes or bits as appropriate for the version used */
/* and bit sequences are input as arrays of bytes in which */
/* bit sequences run from the most to the least significant */
/* end of each byte */
void sha1_compile(sha1_ctx ctx[1]);
void sha1_begin(sha1_ctx ctx[1]);
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]);
void sha1_end(unsigned char hval[], sha1_ctx ctx[1]);
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len);
#if defined(__cplusplus)
}
#endif
#endif

162
tools/types.h Normal file
View File

@@ -0,0 +1,162 @@
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* types.h - Definition of basic cross platform types.
*
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
* $Id: types.h 2333 2007-10-31 19:37:40Z tyranid $
*/
#ifndef __TYPES_H__
#define __TYPES_H__
#include "config.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#else
#include <sys/types.h>
#define uint8_t u_int8_t
#define uint16_t u_int16_t
#define uint32_t u_int32_t
#define uint64_t u_int64_t
#endif
#endif
/* Re-define some system types */
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
#ifdef WORDS_BIGENDIAN
inline u32 lw_le(u32 data)
{
u8 *ptr;
u32 val;
ptr = (u8*) &data;
val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
return val;
}
inline u16 lh_le(u16 data)
{
u8 *ptr;
u16 val;
ptr = (u8*) &data;
val = ptr[0] | (ptr[1] << 8);
return val;
}
#define LW_LE(x) (lw_le((x)))
#define LW_BE(x) (x)
#define LH_LE(x) (lh_le((x)))
#define LH_BE(x) (x)
#else
inline u32 lw_be(u32 data)
{
u8 *ptr;
u32 val;
ptr = (u8*) &data;
val = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
return val;
}
inline u16 lh_be(u16 data)
{
u8 *ptr;
u16 val;
ptr = (u8*) &data;
val = (ptr[0] << 16) | ptr[1];
return val;
}
#define LW_LE(x) (x)
#define LW_BE(x) (lw_be((x)))
#define LH_LE(x) (x)
#define LH_BE(x) (lh_be((x)))
#endif
#define LW(x) (LW_LE(x))
#define LH(x) (LH_LE(x))
#ifdef WORDS_BIGENDIAN
inline void sw_le(u32 *data, u32 val)
{
u8* ptr = (u8*) data;
ptr[0] = (u8) (val & 0xFF);
ptr[1] = (u8) ((val >> 8) & 0xFF);
ptr[2] = (u8) ((val >> 16) & 0xFF);
ptr[3] = (u8) ((val >> 24) & 0xFF);
}
inline void sh_le(u16 *data, u16 val)
{
u8 *ptr = (u8*) data;
ptr[0] = (u8) (val & 0xFF);
ptr[1] = (u8) ((val >> 8) & 0xFF);
}
#define SW_LE(x, v) (sw_le((x), (v)))
#define SW_BE(x, v) (*(x) = (v))
#define SH_LE(x, v) (sh_le((x), (v)))
#define SH_BE(x, v) (*(x) = (v))
#else
inline void sw_be(u32 *data, u32 val)
{
u8 *ptr = (u8*) data;
ptr[0] = (u8) ((val >> 24) & 0xFF);
ptr[1] = (u8) ((val >> 16) & 0xFF);
ptr[2] = (u8) ((val >> 8) & 0xFF);
ptr[3] = (u8) (val & 0xFF);
}
inline void sh_be(u16 *data, u16 val)
{
u8* ptr = (u8*) data;
ptr[0] = (u8) ((val >> 8) & 0xFF);
ptr[1] = (u8) (val & 0xFF);
}
#define SW_LE(x, v) (*(x) = (v))
#define SW_BE(x, v) (sw_be((x), (v)))
#define SH_LE(x, v) (*(x) = (v))
#define SH_BE(x, v) (sh_be((x), (v)))
#endif
#define SW(x, v) (SW_LE(x, v))
#define SH(x, v) (SH_LE(x, v))
#endif

205
tools/unpack-pbp.c Normal file
View File

@@ -0,0 +1,205 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| | ___| ____| | \ PSPDEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 2005 Dan Peori <peori@oopo.net>
# Licenced under Academic Free License version 2.0
# Review pspsdk README & LICENSE files for further details.
#
# 2006-12-26 - Andrew Whatson <whatson@gmail.com>
# - rewrote for easier reading
# - gave "correct" names to UNKNOWN.* files
# - improved memory efficiency with large PBPs
# - no longer outputs empty files
#
# $Id: unpack-pbp.c 2379 2008-04-08 21:18:58Z jim $
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef WORDS_BIGENDIAN
// Swap the bytes of an int for big-endian machines
static int swap_int(int n)
{
return ((n >> 24) & 0xff) | ((n >> 8) & 0xff00) | ((n << 8) & 0xff0000) | ((n << 24) & 0xff000000);
}
#endif
// Struct to describe the header of a PBP file
typedef struct {
char signature[4];
int version;
int offset[8];
} HEADER;
// Correct PBP signature
char correct_sig[4] = {
0x00,
0x50, // P
0x42, // B
0x50 // P
};
// Names of files included in a PBP
char *filename[8] = {
"PARAM.SFO",
"ICON0.PNG",
"ICON1.PMF",
"PIC0.PNG",
"PIC1.PNG",
"SND0.AT3",
"DATA.PSP",
"DATA.PSAR"
};
// Maximum size of read buffer
int maxbuffer = 16 * 1024 * 1024;
int main(int argc, char *argv[]) {
FILE *infile;
FILE *outfile;
HEADER header;
int loop0;
int total_size;
// Check for the correct number of arguments
if (argc != 2) {
printf("USAGE: %s <filename>\n", argv[0]);
return -1;
}
// Open the specified PBP
infile = fopen(argv[1], "rb");
if (infile == NULL) {
printf("ERROR: Could not open the input file. (%s)\n", argv[1]);
return -1;
}
// Get the size of the PBP
fseek(infile, 0, SEEK_END);
total_size = ftell(infile);
fseek(infile, 0, SEEK_SET);
if (total_size < 0) {
printf("ERROR: Could not get the input file size.\n");
return -1;
}
// Read in the header
if (fread(&header, sizeof(HEADER), 1, infile) < 0) {
printf("ERROR: Could not read the input file header.\n");
return -1;
}
// Check the signature
for (loop0 = 0; loop0 < sizeof(correct_sig); loop0++) {
if (header.signature[loop0] != correct_sig[loop0]) {
printf("ERROR: Input file is not a PBP file.\n");
return -1;
}
}
#ifdef WORDS_BIGENDIAN
// Swap the bytes of the offsets for big-endian machines
for (loop0 = 0; loop0 < 8; loop0++) {
header.offset[loop0] = swap_int(header.offset[loop0]);
}
#endif
// For each file in the PBP
for (loop0 = 0; loop0 < 8; loop0++) {
void *buffer;
int size;
// Get the size of this file
if (loop0 == 7) {
size = total_size - header.offset[loop0];
} else {
size = header.offset[loop0 + 1] - header.offset[loop0];
}
// Print out the file details
printf("[%d] %10d bytes | %s\n", loop0, size, filename[loop0]);
// Skip the file if empty
if (!size) continue;
// Seek to the proper position in the file
if (fseek(infile, header.offset[loop0], SEEK_SET) != 0) {
printf("ERROR: Could not seek in the input file.\n");
return -1;
}
// Open the output file
outfile = fopen(filename[loop0], "wb");
if (outfile == NULL) {
printf("ERROR: Could not open the output file. (%s)\n", filename[loop0]);
return -1;
}
do {
int readsize;
// Make sure we don't exceed the maximum buffer size
if (size > maxbuffer) {
readsize = maxbuffer;
} else {
readsize = size;
}
size -= readsize;
// Create the read buffer
buffer = malloc(readsize);
if (buffer == NULL) {
printf("ERROR: Could not allocate the section data buffer. (%d)\n", readsize);
return -1;
}
// Read in the data from the PBP
if (fread(buffer, readsize, 1, infile) < 0) {
printf("ERROR: Could not read in the section data.\n");
return -1;
}
// Write the contents of the buffer to the output file
if (fwrite(buffer, readsize, 1, outfile) < 0) {
printf("ERROR: Could not write out the section data.\n");
return -1;
}
// Clean up the buffer
free(buffer);
// Repeat if we haven't finished writing the file
} while (size);
// Close the output file
if (fclose(outfile) < 0) {
printf("ERROR: Could not close the output file.\n");
return -1;
}
}
// Close the PBP
if (fclose(infile) < 0) {
printf("ERROR: Could not close the input file.\n");
return -1;
}
// Exit successful
return 0;
}