I've written a quick and dirty PSP Header Parser thats rougly based on Gorims SFO parser:
Update:
Fixed infinty loop bug under linux - thanks to fireether for pointing it out
Code: Select all
// PSPParse.cpp : Defines the entry point for the console 
application.
//
#include "stdafx.h"
/*
 * PSP File Parser v 0.1, based on Gorims SFO parser
 *
 * This source is licensed under the terms of the Academic Free License 
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRBUFSZ 512
// Some data type definitions for Intel Doze platforms, 2005/05/06
typedef unsigned int u_int32_t;
typedef unsigned short int u_int16_t ;
typedef unsigned char u_int8_t;
/* Change endianess*/ 
u_int32_t le32(int i)
{
  unsigned char b1, b2, b3, b4;
  b1 = i & 255;
  b2 = ( i >> 8 ) & 255;
  b3 = ( i>>16 ) & 255;
  b4 = ( i>>24 ) & 255;
  return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4;
}
u_int16_t le16(short s )
{
  unsigned char b1, b2;
  
  b1 = s & 255;
  b2 = (s >> 8) & 255;
  return (b1 << 8) + b2;
}
struct PSPHdr
{
   u_int8_t		type[4];
   u_int32_t	version;
   u_int16_t	sect1;
   u_int8_t		title[28];
   u_int16_t	sect2;
   u_int32_t	size[2];
   u_int32_t	unkwn_ptr[3];
   u_int32_t	sect3;
   u_int32_t	nulls[40];
};
char pspMagic[] = "~PSP";
char DefaultFile[] = "DATA.PSP";
int main(int argc, char *argv[])
{
   FILE      *PSPFile;
   char      *Filename;
   struct    PSPHdr   *header;
   u_int8_t  *psp;
   int       fsize, i, nc;
   Filename = (argc != 2) ? DefaultFile : argv[1];
   if (!(PSPFile = fopen(Filename, "r+b")))
   {
      perror("File cannot be opened.");
      exit(1);
   }
   fseek(PSPFile, 0, SEEK_END);
   fsize = ftell(PSPFile);
   psp = (u_int8_t*)malloc(fsize);
   rewind(PSPFile);
   fread(psp, fsize, 1, PSPFile);
   fclose(PSPFile);
   if (memcmp(pspMagic, psp, 4))
   {
      printf("WARNING: %s is not a PSP file !\n", Filename);
   }
   header = (struct PSPHdr*)psp;
   
printf("=============================================================================\n");
   printf("PlayStation Portable PSP File Data\n");
   
printf("=============================================================================\n");
   printf("\nFilename: %s\n", Filename);
   //\tFilesize           : %i\n", fsize
   
   printf("Exe-Type      : %c%c%c%c\t\tFile Type           : %08x\n\n"
	   ,header->type[0],header->type[1],header->type[2],header->type[3], le32(header->version));
   printf("Title           : %s\n", header->title);
   
   printf("Section1        : %04x\t\tSection2            : %04x\n", le16(header->sect1), le16(header->sect2));
  // printf("Section       : %04x\n", le16(header->sect2));
   printf("Size (unenc.)   : %i\tEnc-to-Unenc Diff   : %i\n", header->size[0], abs(header->size[1] - header->size[0]));
   if(int(header->size[1]) == int(fsize)){
   printf("Size (enc.)     : %i\tequals Filesize     : yes\n\n", header->size[1]);
   }
   else{
   printf("Size (enc.)     : %i\tEquals Filesize     :  NO!!!!\n\n", header->size[1]);
   }
   nc = 0;
   for (i = 0; i <= 2; i ++){
   printf("Unkown Pointer%i : %08x\tValue:  %i\n",i+1, le32(header->unkwn_ptr[i]), header->unkwn_ptr[i]);
   }
   printf("Section3        : %08x\n\n", le32(header->sect3));
   printf("2 x usual NULLs : %08x  %08x, followed by %08x\n",le32(header->nulls[0]), le32(header->nulls[1]), le32(header->nulls[2]));
   printf("2 x usual NULLs : %08x  %08x, followed by %08x (last 3 bytes !?)\n",le32(header->nulls[3]), le32(header->nulls[4]), le32(header->nulls[5]));
   printf("Unkown Data     : %08x\t Value:  %i\n\n", le32(header->nulls[6]), header->nulls[6]);
   
   printf("8 x usual NULLs : %08x  %08x  %08x  %08x\n                  %08x  %08x  %08x  %08x\n",
   le32(header->nulls[7]), le32(header->nulls[8]), le32(header->nulls[9]), le32(header->nulls[10]),
   le32(header->nulls[11]), le32(header->nulls[12]), le32(header->nulls[13]), le32(header->nulls[14]));
   printf("Unkown Data     : %08x\t Value:  %i\n\n", le32(header->nulls[15]), header->nulls[15]);
   printf("Key/MD5/Encrypted Start Sequence ??\n");
   for (i = 16; i < 28; i ++){
   printf("%08x ",le32(header->nulls[i]));
	 if ((i+1)%4==0){
		 printf("\n");
	 }
   }
   if (int(header->nulls[28]) == int(header->size[0])){
   printf("\nUnkown Data     : %08x\t Value:  %i  matches Size (unenc.): yes\n", le32(header->nulls[28]), header->nulls[28]);
   }
   else{
   printf("\nUnkown Data     : %08x\t Value:  %i  matches Size (unenc.): NO!\n", le32(header->nulls[28]), header->nulls[28]);
   printf("   Size (unenc.): %08x\t Value:  %i\n", le32(header->size[0]), header->size[0]);
   printf("   Size (enc.)  : %08x\t Value:  %i\n\n", le32(header->size[1]), header->size[1]);
   }
   printf("Unkown Data     : %08x\t Value:  %i      hint to %ibit AES ?\n", le32(header->nulls[29]), header->nulls[29], header->nulls[29]);
   printf("6 Values (normally NULL) %i, %i, %i, %i, %i, %i followed by 0x%08x\n",header->nulls[30],header->nulls[31], header->nulls[32],header->nulls[33], header->nulls[34], header->nulls[35], le32(header->nulls[36]));
   
printf("=============================================================================\n");
   return 0;
} 
Here's the output of the latest Firmware 1.51
=============================================================================
PlayStation Portable PSP File Data
=============================================================================
Filename: firmware\1.51\content\DATA.PSP
Exe-Type      : ~PSP            File Type           : 00080000
Title           : updater
Section1        : 0101          Section2            : 0102
Size (unenc.)   : 3703968       Enc-to-Unenc Diff   : 336
Size (enc.)     : 3704304       equals Filesize     : yes
Unkown Pointer1 : 18300000      Value:  12312
Unkown Pointer2 : 68430f00      Value:  1000296
Unkown Pointer3 : b45f0300      Value:  221108
Section3        : 40004000
2 x usual NULLs : 00000000  00000000, followed by 004a1000
2 x usual NULLs : 00000000  00000000, followed by 004a1000 (last 3 bytes !?)
Unkown Data     : 40702600       Value:  2519104
8 x usual NULLs : 00000000  00000000  00000000  00000000
                  00000000  00000000  00000000  00000000
Unkown Data     : 0c000000       Value:  12
Key/MD5/Encrypted Start Sequence ??
7dd213c7 858fa3b3 0e728038 5f7dd546
a0eb88a2 9ff70b7a 77c9199c cd8a8efb
fc389e7b fec3b73b aa11d9db 28acabbd
Unkown Data     : a0843800       Value:  3703968  matches Size (unenc.): yes
Unkown Data     : 80000000       Value:  128      hint to 128bit AES ?
6 Values (normally NULL) 0, 0, 0, 0, 0, 0 followed by 0x0000000b
=============================================================================