PUP: Difference between revisions

From PS4 Developer wiki
Jump to navigation Jump to search
(Add info on PUP structure and update C structs)
Line 1: Line 1:
PUP (Playstation Update Package) is the file format of the PSP, PS3, PSVita and PS4 system software update packages.
PUP (Playstation Update Package) is the file format of the PSP, PS3, PSVita, PS4, and PS5 system software update packages. It contains updated firmware and files for devices such as the GameOS, Syscon, Wi-Fi, Bluetooth, Communication Processor, Southbridge, BD drive, and more.


PUP embed updates for devices such as the GameOS, Syscon, Wi-Fi, Bluetooth, Communication Processor, Southbridge, BD drive.
== PUP Structure ==


== Structure ==
PS4 update files differ from previous consoles in that they embed multiple PUP fragments. The "main" file that's distributed and downloaded to the console is an SLB2-packed (or "BLS") file which contains PUP fragment files. On retail and testkits, it typically contains two PUPs (`PS4UPDATE1.PUP` and `PS4UPDATE2.PUP`), while devkits may have four. These PUP files are similar in structure to Signed ELFs (SELFs). Each update fragment is responsible for containing different sets of firmware and files.


PS4 PUP is special because it embeds single other PUPs.
* PS4UPDATE1 is the "core" update file and contains updates for GameOS/x86 kernel and libraries, BluRay, EAP, EMC, Syscon, SAMU, and other firmware stored on the SPI flash.
* PS4UPDATE2 contains the `system_ex` partition of system apps.
* PS4UPDATE3 (devkits) contains the preinstall image for devkit files.
* PS4UPDATE4 (devkits) contains a seemingly empty preinstall part 2 image (maybe reserved?).


=== Header ===
All update fragments contain the EULA, the Orbis Software Updater (orbis_swu), and a watermark.


Have a feeling the header for the new PS4 PUPs ends with a LZMA dictionary and file size… (ie a normal lzma header without the properties byte) anyone else done research into that? As in:
=== File Header ===
 
The file header for the main PUP file is an SLB2 file. Each pup fragment packed into it has the following header (note: after the initial 0x10 bytes, the remaining 0x10 bytes are encrypted along with the metadata that follows it).
 
<source lang="c">
struct ScePupHeader {
uint32_t magic;                 // 0x00 - PS4PUPMAGIC "\x4F\x15\x3D\x1D"
uint16_t version;              // 0x04 - Big Endian (??)
uint16_t unknown_one;          // 0x06
uint16_t unknown_two;          // 0x08
uint16_t flags;                // 0x0A
uint16_t header_size;          // 0x0C
uint16_t metadata_size;        // 0x0E
 
// From this point on, the header is encrypted...
uint16_t file_size;            // 0x10
uint16_t segment_count;        // 0x18
uint16_t metadata_entries;      // 0x1A
uint32_t unknown_three;        // 0x1C
}; // Size: 0x20
</source>
 
=== Segments ===
 
From this point on, the remaining structures are encrypted in raw update files (though this section can be seen by using the system as an oracle to decrypt PUPs). Following the header is the segment table, which has segment entries that contain information about update entries (a list of which can be found in the "Indices" section).
 
<source lang="c">
struct ScePupSegmentHeader {
uint64_t flags;                // 0x00
uint64_t offset;                // 0x08
uint64_t compressed_size;      // 0x10
uint64_t uncompressed_size;    // 0x18
}; // Size: 0x20
</source>
 
While offset, compressed_size, and uncompressed_size fields are self-explanatory, the flags field packs a lot of information. Below are known flags:
 
<source lang="c">
#define PUP_SEGMENT_ID(x)                  (x->flags >> 20)
#define PUP_SEGMENT_IS_INFO(x)              ((x->flags & (1 << 0)) != 0)
#define PUP_SEGMENT_IS_ENCRYPTED(x)        ((x->flags & (1 << 1)) != 0)
#define PUP_SEGMENT_IS_SIGNED(x)            ((x->flags & (1 << 2)) != 0)
#define PUP_SEGMENT_IS_COMPRESSED(x)        ((x->flags & (1 << 3)) != 0)
#define PUP_SEGMENT_HAS_BLOCKS(x)          ((x->flags & (1 << 11)) != 0)
#define PUP_SEGMENT_HAS_DIGESTS(x)          ((x->flags & (1 << 16)) != 0)
#define PUP_SEGMENT_BLOCK_SIZE(x)          (1 << (((x->flags >> 12) & 0xF) + PAGE_SHIFT)) // Note: PAGE_SHIFT = 0xC
</source>
 
In most cases (ie. "data" segments as opposed to info segments), the segment ID indicates the type of firmware or file to update (see: "Indices" table). In the case of info segments, the segment ID points to the index of the "data" segment it contains information for. Info segments are typically only seen when the file or firmware utilizes block-based segments.
 
=== PUP Info ===
 
After the segment table is a section that has additional information on the PUP, such as its target firmware and various flags.


<source lang="c">
<source lang="c">
struct PUPPS4Header {
struct ScePupInfo {
uint32_t magic; // PS4PUPMAGIC "\x4F\x15\x3D\x1D"
uint32_t fw_ver;               // 0x00 - Firmware version in integer format (ie. FW 9.50 is 0x95080000000)
uint16_t version; // Big Endian (??)
char unknown_one[0x14];         // 0x04
uint16_t unknownOne;
uint32_t type;                 // 0x18 - Beta/Retail/Testkit/Devkit/Proto
uint16_t unknownTwo;
char unknown_two[0x4];         // 0x1C
uint16_t unknownThree;
uint32_t flags;                 // 0x20
uint32_t dictSize; // LE afaics
uint32_t req_fw_ver;           // 0x24
uint32_t uncompressedSize; // LE afaics
char unknown_three[0x8];       // 0x28
}
}
</source>
</source>
=== Metadata ===
Following the info structure is the metadata table. These entries contain crypto material such as intermediate keys for decrypting and verifying segments. Each segment should have a metadata table entry.
<source lang="c">
struct ScePupMetadataEntry {
char aes128_key[0x10];          // 0x00 - AES128 data decryption key
char aes128_iv[0x10];          // 0x10 - AES128 data decryption initialization vector
char digest[0x20];              // 0x20 - SHA256 digest
char digest_key[0x10];          // 0x40 - SHA256 digest HMAC key
}; // Size: 0x50
</source>
=== Unpacking Notes ===
* Encryption is applied on segments post-compression.
* Non-blocked segments are a straight copy or decompression operation.
* Processing blocked segments requires looking up the accompanying info segments and parsing the block tables within them.
* Large disk images and most SLB2/BLS files will be block-based.


== Tools ==
== Tools ==

Revision as of 02:02, 6 August 2023

PUP (Playstation Update Package) is the file format of the PSP, PS3, PSVita, PS4, and PS5 system software update packages. It contains updated firmware and files for devices such as the GameOS, Syscon, Wi-Fi, Bluetooth, Communication Processor, Southbridge, BD drive, and more.

PUP Structure

PS4 update files differ from previous consoles in that they embed multiple PUP fragments. The "main" file that's distributed and downloaded to the console is an SLB2-packed (or "BLS") file which contains PUP fragment files. On retail and testkits, it typically contains two PUPs (`PS4UPDATE1.PUP` and `PS4UPDATE2.PUP`), while devkits may have four. These PUP files are similar in structure to Signed ELFs (SELFs). Each update fragment is responsible for containing different sets of firmware and files.

  • PS4UPDATE1 is the "core" update file and contains updates for GameOS/x86 kernel and libraries, BluRay, EAP, EMC, Syscon, SAMU, and other firmware stored on the SPI flash.
  • PS4UPDATE2 contains the `system_ex` partition of system apps.
  • PS4UPDATE3 (devkits) contains the preinstall image for devkit files.
  • PS4UPDATE4 (devkits) contains a seemingly empty preinstall part 2 image (maybe reserved?).

All update fragments contain the EULA, the Orbis Software Updater (orbis_swu), and a watermark.

File Header

The file header for the main PUP file is an SLB2 file. Each pup fragment packed into it has the following header (note: after the initial 0x10 bytes, the remaining 0x10 bytes are encrypted along with the metadata that follows it).

struct ScePupHeader {
	uint32_t magic;	                // 0x00 - PS4PUPMAGIC "\x4F\x15\x3D\x1D"
	uint16_t version;               // 0x04 - Big Endian (??)
	uint16_t unknown_one;           // 0x06
	uint16_t unknown_two;           // 0x08
	uint16_t flags;                 // 0x0A
	uint16_t header_size;           // 0x0C
	uint16_t metadata_size;         // 0x0E

	// From this point on, the header is encrypted...
	uint16_t file_size;             // 0x10
	uint16_t segment_count;         // 0x18
	uint16_t metadata_entries;      // 0x1A
	uint32_t unknown_three;         // 0x1C
}; // Size: 0x20

Segments

From this point on, the remaining structures are encrypted in raw update files (though this section can be seen by using the system as an oracle to decrypt PUPs). Following the header is the segment table, which has segment entries that contain information about update entries (a list of which can be found in the "Indices" section).

struct ScePupSegmentHeader {
	uint64_t flags;                 // 0x00
	uint64_t offset;                // 0x08
	uint64_t compressed_size;       // 0x10
	uint64_t uncompressed_size;     // 0x18
}; // Size: 0x20

While offset, compressed_size, and uncompressed_size fields are self-explanatory, the flags field packs a lot of information. Below are known flags:

#define PUP_SEGMENT_ID(x)                   (x->flags >> 20)
#define PUP_SEGMENT_IS_INFO(x)              ((x->flags & (1 << 0)) != 0)
#define PUP_SEGMENT_IS_ENCRYPTED(x)         ((x->flags & (1 << 1)) != 0)
#define PUP_SEGMENT_IS_SIGNED(x)            ((x->flags & (1 << 2)) != 0)
#define PUP_SEGMENT_IS_COMPRESSED(x)        ((x->flags & (1 << 3)) != 0)
#define PUP_SEGMENT_HAS_BLOCKS(x)           ((x->flags & (1 << 11)) != 0)
#define PUP_SEGMENT_HAS_DIGESTS(x)          ((x->flags & (1 << 16)) != 0)
#define PUP_SEGMENT_BLOCK_SIZE(x)           (1 << (((x->flags >> 12) & 0xF) + PAGE_SHIFT)) // Note: PAGE_SHIFT = 0xC

In most cases (ie. "data" segments as opposed to info segments), the segment ID indicates the type of firmware or file to update (see: "Indices" table). In the case of info segments, the segment ID points to the index of the "data" segment it contains information for. Info segments are typically only seen when the file or firmware utilizes block-based segments.

PUP Info

After the segment table is a section that has additional information on the PUP, such as its target firmware and various flags.

struct ScePupInfo {
	uint32_t fw_ver;                // 0x00 - Firmware version in integer format (ie. FW 9.50 is 0x95080000000)
	char unknown_one[0x14];         // 0x04
	uint32_t type;                  // 0x18 - Beta/Retail/Testkit/Devkit/Proto
	char unknown_two[0x4];          // 0x1C
	uint32_t flags;                 // 0x20
	uint32_t req_fw_ver;            // 0x24
	char unknown_three[0x8];        // 0x28
}

Metadata

Following the info structure is the metadata table. These entries contain crypto material such as intermediate keys for decrypting and verifying segments. Each segment should have a metadata table entry.

struct ScePupMetadataEntry {
	char aes128_key[0x10];          // 0x00 - AES128 data decryption key
	char aes128_iv[0x10];           // 0x10 - AES128 data decryption initialization vector
	char digest[0x20];              // 0x20 - SHA256 digest
	char digest_key[0x10];          // 0x40 - SHA256 digest HMAC key
}; // Size: 0x50

Unpacking Notes

  • Encryption is applied on segments post-compression.
  • Non-blocked segments are a straight copy or decompression operation.
  • Processing blocked segments requires looking up the accompanying info segments and parsing the block tables within them.
  • Large disk images and most SLB2/BLS files will be block-based.

Tools

Decrypter (first step)

Unpacker (second step)

Indices

Index Decimal Description Perconsole? Notes Added Deprecated? Cipher Note Component Name
1 1 EMC IPL No sflash0s0x32/b Aeolia 1st Revision 0.910.040 Yes , since 2.00 Same body as 0x0D ??
2 2 EAP KBL No sflash0s0x33 Aeolia 1st Revision 0.910.040 Yes , since 2.00 Same body as 0x0E ??
3 3 WIFI FW No torus2 Aeolia A2 0.910.040 --
4 4 SAM IPL Yes sflash0s1.cryptx2/b 1st SOCUID 0.910.040 (Confirmed by anon) Same body as 0x23 CXD90026G
5 5 COREOS No secure_modules 0.910.040 GEN1,2,3 Universal
6 6 SYSTEM No system fs (FAT32/TEXFAT later) 0.910.040 GEN1,2,3 Universal
7 7 EAP KERNEL No da0x2 0.910.040 GEN1,2,3 Universal
8 8 EAP VSH No eap_vsh fs (FAT16) 0.910.040 GEN1,2,3 Universal
9 9 PREINST No preinst fs (FAT32) 0.910.040 GEN1,2,3 Universal
0xA 10 ??? No sflash0s1.cryptx40 No ??
0xB 11 PREINST2 No preinst2 fs (FAT32) 0.910.040 GEN1,2,3 Universal
0xC 12 SYSTEM_EX No system_ex fs (FAT32/TEXFAT later) 0.910.040 GEN1,2,3 Universal
0xD 13 EMC IPL No sflash0s0x32/b Aeolia A2 0.910.040 Same body as 0x1 CXD90025G
0xE 14 EAP KBL No sflash0s0x33 Aeolia A2 0.910.040 Same body as 0x2 CXD90025G
0xF 15 ??? No test No ??
0x10-0x16 16-22 ??? No sbram0 No ??
0x20 32 EMC IPL No sflash0s0x32/b Belize 1st Revision 2.00 Same body as 0x2A CXD90036G
0x21 33 EAP KBL No sflash0s0x33 Belize 1st Revision 2.00 Same body as 0x2B and 0x25 CXD90036G
0x22 34 WIFI FW No torus2 2.00 ??
0x23 35 SAM IPL Yes sflash0s1.cryptx2/b 2nd SOCUID 2.00 (Confirmed by anon) Same body as 0x04 CXD90026AG
0x24 36 EMC IPL No sflash0s0x32/b Baikal B1 3.00 CXD90046GG
0x25 37 EAP KBL No sflash0s0x33 Baikal B1 3.00 Same body as 0x2B and 0x21 CXD90046GG
0x26 38 SAM IPL Yes sflash0s1.cryptx2/b 3rd SOCUID 3.00 (Confirmed by anon) Same body as 0x2D and 0x32 CXD90037G
0x27 39 SAM IPL Yes sflash0s1.cryptx2/b 4th SOCUID 3.00 (Confirmed by anon) Same body as 0x31 CXD90043GB
0x28 40 EMC IPL No sflash0s0x32/b Baikal 1st Revision 3.00 Same body as 0x2C
0x2A 42 EMC IPL No sflash0s0x32/b Belize 2 A0 4.00 Same body as 0x20
0x2B 43 EAP KBL No sflash0s0x33 Belize 2 A0 4.00 Same body as 0x25 and 0x21
0x2C 44 EMC IPL No sflash0s0x32/b Baikal2 1st Revision 4.00 Same body as 0x28
0x2D 45 SAM IPL Yes sflash0s1.cryptx2/b 5th SOCUID 4.50 (Confirmed by anon) Same body as 0x26 and 0x32 CXD90044GB
0x2E 46 EMC IPL No sflash0s0x32/b Belize2 3rd Revision? 5.00
0x30 48 WIFI FW No sflash0s0x38 trooper Belize 2 A0 5.00 --
0x31 49 SAM IPL Yes sflash0s1.cryptx2/b 6th SOCUID 5.50 (Confirmed by anon) Same body as 0x27 CXD90051GB
0x32 50 SAM IPL Yes sflash0s1.cryptx2/b 7th SOCUID 6.50 (Confirmed by anon) Same body as 0x26 and 0x2D CXD90055GB
0x101 257 EULA.XML No Sony Agreement XML 1.00 Universal
0x200 512 ORBIS_SWU.SELF No Sony SoftWareUpdater (ELF) 0.910.040 Universal
0x202 514 ORBIS_SWU.SELF No Sony SoftWareUpdater (Encrypted SELF) 0.920.030 Universal
0x301 769 ??? No /update related No ??
0x302 770 ??? No /update related No ??
0xD00 3328 SYSCON FW No sc_fw_update0 firmware (4000XXXX) 0.915.010 Universal Syscon
0xD01 3329 BLURAY FW No bluray firmware (all revisions) (4XXR) 0.920.030 Universal Bluray
0xD02 3330 USB SATA BRIDGE FW No usb sata bridge firmware (da0) 1.00 MB86C311B
0xD07 3335 SYSCON PATCH No sc_fw_update0 patch (4001XXXX) 2.50 Test/Retail Universal Syscon
0xD08 3336 SYSCON FW No sc_fw_update0 firmware (4000XXXX) 1.00 Devkit Universal Syscon
0xD09 3337 COMMUNICATION PROCESSOR FW No cpfirm 3.50 Devkit Neo Devkit Component (unknown)