mirror of
https://github.com/joel16/uofw.git
synced 2024-12-03 17:01:35 +00:00
Make the build system work EXACTLY the same way as for official kernel modules.
Fixed alignment. Added our/my own version of psp-build-exports from the PSPSDK, so the library name is placed right before the library exports in .rodata. Added our/my own version of psp-prxgen from the PSPSDK (named psp-kprxgen for us), so the module uses only program headers and absolutely no sections.
This commit is contained in:
parent
0202f8712a
commit
484569d7fb
@ -23,10 +23,10 @@ $(TARGET).elf: $(OBJS) $(EXPORT_OBJ)
|
||||
-$(FIXUP) $@
|
||||
|
||||
%.prx: %.elf
|
||||
psp-prxgen $< $@
|
||||
../../utils/kprxgen/psp-kprxgen $< $@
|
||||
|
||||
%.c: %.exp
|
||||
psp-build-exports -b $< > $@
|
||||
../../utils/build-exports/psp-build-exports -b $< > $@
|
||||
|
||||
clean:
|
||||
-rm -f $(TARGET).prx $(TARGET).elf $(EXPORT_OBJ) $(OBJS)
|
||||
|
@ -2,6 +2,7 @@
|
||||
OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips",
|
||||
"elf32-littlemips")
|
||||
OUTPUT_ARCH(mips:allegrex)
|
||||
ENTRY(module_start)
|
||||
/* SEARCH_DIR("/usr/local/pspdev/psp/lib"); */
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
@ -72,6 +73,7 @@ SECTIONS
|
||||
*(.gnu.warning)
|
||||
*(.mips16.fn.*) *(.mips16.call.*)
|
||||
} =0
|
||||
. = ALIGN(16);
|
||||
.init :
|
||||
{
|
||||
KEEP (*(.init))
|
||||
@ -108,9 +110,6 @@ SECTIONS
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = ALIGN(256) + (. & (256 - 1));
|
||||
/* Exception handling */
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
|
||||
|
@ -77,15 +77,16 @@ enum PspModuleInfoAttr
|
||||
extern char __lib_stub_top[], __lib_stub_bottom[]; \
|
||||
SceModuleInfo module_info \
|
||||
__attribute__((section(".rodata.sceModuleInfo"), \
|
||||
aligned(16), unused)) = { \
|
||||
, unused)) = { \
|
||||
attributes, { minor_version, major_version }, name, 0, _gp, \
|
||||
__lib_ent_top, __lib_ent_bottom, \
|
||||
__lib_stub_top, __lib_stub_bottom \
|
||||
}
|
||||
|
||||
#define PSP_SDK_VERSION(ver) int syslib_11B97506 = ver
|
||||
#define PSP_SDK_VERSION(ver) const int syslib_11B97506 = ver
|
||||
|
||||
#define PSP_MODULE_BOOTSTART(name) int module_bootstart(int arglen, void *argp) __attribute__((alias(name)))
|
||||
#define PSP_MODULE_BOOTSTART(name) int module_start(int arglen, void *argp) __attribute__((alias(name))); \
|
||||
int module_bootstart(int arglen, void *argp) __attribute__((alias(name)))
|
||||
|
||||
/********** TEMPORARY: it'll be in their corresponding module's header *********/
|
||||
typedef int (*SceKernelCallbackFunction)(int arg1, int arg2, void *arg);
|
||||
|
27
utils/build-exports/Makefile
Normal file
27
utils/build-exports/Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
# Copyright (C) 2011 The uOFW team
|
||||
# See the file COPYING for copying permission.
|
||||
|
||||
CPP=gcc
|
||||
CFLAGS=-Wall -Wextra -Werror
|
||||
LDFLAGS=
|
||||
TARGET=psp-build-exports
|
||||
OBJECTS=sha1.o psp-build-exports.o
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
@echo "Creating binary $(TARGET)"
|
||||
@$(CPP) $(OBJECTS) -o $@ $(LDFLAGS)
|
||||
|
||||
%.o: %.cpp
|
||||
@echo "Compiling $^"
|
||||
$(CPP) $(CFLAGS) -c $^ -o $@
|
||||
|
||||
clean:
|
||||
@echo "Removing all the .o files"
|
||||
@$(RM) $(OBJECTS)
|
||||
|
||||
mrproper: clean
|
||||
@echo "Removing binary"
|
||||
@$(RM) $(TARGET)
|
||||
|
1050
utils/build-exports/psp-build-exports.c
Normal file
1050
utils/build-exports/psp-build-exports.c
Normal file
File diff suppressed because it is too large
Load Diff
282
utils/build-exports/sha1.c
Normal file
282
utils/build-exports/sha1.c
Normal 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
utils/build-exports/sha1.h
Normal file
84
utils/build-exports/sha1.h
Normal 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
|
27
utils/kprxgen/Makefile
Normal file
27
utils/kprxgen/Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
# Copyright (C) 2011 The uOFW team
|
||||
# See the file COPYING for copying permission.
|
||||
|
||||
CPP=gcc
|
||||
CFLAGS=-Wall -Wextra -Werror
|
||||
LDFLAGS=
|
||||
TARGET=psp-kprxgen
|
||||
OBJECTS=psp-kprxgen.o
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
@echo "Creating binary $(TARGET)"
|
||||
@$(CPP) $(OBJECTS) -o $@ $(LDFLAGS)
|
||||
|
||||
%.o: %.cpp
|
||||
@echo "Compiling $^"
|
||||
$(CPP) $(CFLAGS) -c $^ -o $@
|
||||
|
||||
clean:
|
||||
@echo "Removing all the .o files"
|
||||
@$(RM) $(OBJECTS)
|
||||
|
||||
mrproper: clean
|
||||
@echo "Removing binary"
|
||||
@$(RM) $(TARGET)
|
||||
|
246
utils/kprxgen/elftypes.h
Normal file
246
utils/kprxgen/elftypes.h
Normal 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
|
150
utils/kprxgen/prxtypes.h
Normal file
150
utils/kprxgen/prxtypes.h
Normal 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
|
815
utils/kprxgen/psp-kprxgen.c
Normal file
815
utils/kprxgen/psp-kprxgen.c
Normal file
@ -0,0 +1,815 @@
|
||||
/* Copyright (C) 2011 The uOFW team
|
||||
See the file COPYING for copying permission.
|
||||
|
||||
Based on the original file from PSPSDK, written by tyranid; many thanks to him!
|
||||
*/
|
||||
|
||||
#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;
|
||||
static struct ElfSection *g_elfsections = NULL;
|
||||
static struct ElfSection *g_modinfo = NULL;
|
||||
static int g_alloc_size = 0;
|
||||
static int g_reloc_size = 0;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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()
|
||||
{
|
||||
int ret = 0;
|
||||
int found_rel = 0;
|
||||
unsigned int load_addr = 0xFFFFFFFF;
|
||||
|
||||
if(g_elfhead.iShnum > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
Elf32_Shdr *sect;
|
||||
u32 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)
|
||||
{
|
||||
u32 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)
|
||||
{
|
||||
u32 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())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(!process_relocs())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
reindex_sections();
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
while(0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int calculate_outsize(void)
|
||||
{
|
||||
u32 alloc_size = 0;
|
||||
int reloc_size = 0;
|
||||
u32 i;
|
||||
|
||||
/* Calculate how big our output file needs to be */
|
||||
/* We have elf header + 3 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 = g_elfsections[i].iAddr + g_elfsections[i].iSize;
|
||||
if(top_addr > alloc_size)
|
||||
{
|
||||
alloc_size = top_addr;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
alloc_size = (alloc_size + 3) & ~3;
|
||||
|
||||
/* Save them for future use */
|
||||
g_alloc_size = alloc_size;
|
||||
g_reloc_size = reloc_size;
|
||||
|
||||
/* Lets build the offsets */
|
||||
g_phbase = sizeof(Elf32_Ehdr);
|
||||
/* The allocated data needs to be 64 byte aligned (probably; seen in kernel .prx files) */
|
||||
g_allocbase = (g_phbase + 3 * sizeof(Elf32_Phdr) + 0x3F) & ~0x3F;
|
||||
g_relocbase = g_allocbase + g_alloc_size;
|
||||
|
||||
return g_relocbase + g_reloc_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, 3);
|
||||
SH(&head->e_shentsize, 0);
|
||||
SH(&head->e_shnum, 0);
|
||||
SH(&head->e_shstrndx, 0);
|
||||
}
|
||||
|
||||
struct ElfSection *get_sh(const char *name)
|
||||
{
|
||||
u32 i;
|
||||
for(i = 0; i < g_elfhead.iShnum; i++)
|
||||
if (strcmp(name, g_elfsections[i].szName) == 0)
|
||||
return &g_elfsections[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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_alloc_size);
|
||||
SW(&phdr->p_flags, 5);
|
||||
SW(&phdr->p_align, 0x40);
|
||||
|
||||
/* Second program header */
|
||||
phdr++;
|
||||
|
||||
SW(&phdr->p_type, 1);
|
||||
SW(&phdr->p_offset, get_sh(".data")->iAddr + g_allocbase);
|
||||
SW(&phdr->p_vaddr, get_sh(".data")->iAddr);
|
||||
SW(&phdr->p_paddr, 0);
|
||||
SW(&phdr->p_filesz, get_sh(".data")->iSize);
|
||||
SW(&phdr->p_memsz, get_sh(".data")->iSize + get_sh(".bss")->iSize);
|
||||
SW(&phdr->p_flags, 6);
|
||||
SW(&phdr->p_align, 0x40);
|
||||
|
||||
/* Third program header */
|
||||
phdr++;
|
||||
|
||||
SW(&phdr->p_type, 0x700000A1);
|
||||
SW(&phdr->p_offset, g_relocbase);
|
||||
SW(&phdr->p_vaddr, 0);
|
||||
SW(&phdr->p_paddr, 0);
|
||||
SW(&phdr->p_filesz, g_reloc_size);
|
||||
SW(&phdr->p_memsz, 0);
|
||||
SW(&phdr->p_flags, 0);
|
||||
SW(&phdr->p_align, 0x10);
|
||||
}
|
||||
|
||||
/* Output the allocated sections */
|
||||
void output_alloc(unsigned char *data)
|
||||
{
|
||||
u32 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 relocations */
|
||||
void output_relocs(unsigned char *data)
|
||||
{
|
||||
u32 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 a stripped prx file */
|
||||
int output_prx(const char *prxfile)
|
||||
{
|
||||
int size;
|
||||
unsigned char *data;
|
||||
FILE *fp;
|
||||
|
||||
do
|
||||
{
|
||||
size = calculate_outsize();
|
||||
data = 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_relocs(data + g_relocbase);
|
||||
|
||||
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;
|
||||
}
|
149
utils/kprxgen/types.h
Normal file
149
utils/kprxgen/types.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
/* 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
|
Loading…
Reference in New Issue
Block a user