diff --git a/Makefile b/Makefile index 710943d..5f98fb5 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,8 @@ $(SC_HV_H): $(SC_K_H): $(MAKE) -C shellcode_kernel +source/firmware.o: scripts/ubuntu/initramfs-tools scripts/ubuntu/ps5-wifi-fw + $(OBJS): %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/include/cpio.h b/include/cpio.h new file mode 100644 index 0000000..f6b326a --- /dev/null +++ b/include/cpio.h @@ -0,0 +1,19 @@ +#ifndef CPIO_H +#define CPIO_H + +#include +#include + +#define CPIO_MODE_DIR 0040755 +#define CPIO_MODE_FILE 0100644 + +size_t cpio_newc_entry_size(const char *name, size_t data_size); +size_t cpio_newc_parent_dirs_size(const char *path); +uint8_t *cpio_newc_data(uint8_t *entry, const char *name); +uint8_t *cpio_newc_write_entry(uint8_t *out, const char *name, uint32_t mode, + const void *data, size_t data_size, + uint32_t ino); +uint8_t *cpio_newc_write_parent_dirs(uint8_t *out, const char *path, + uint32_t *ino); + +#endif diff --git a/include/firmware.h b/include/firmware.h index fa79670..f94b4de 100644 --- a/include/firmware.h +++ b/include/firmware.h @@ -1,6 +1,12 @@ #ifndef FIRMWARE_H #define FIRMWARE_H +<<<<<<< dev-wifi-fw int dump_device_firmwares(const char *boot_file_path); +======= +#include + +int resolve_device_firmwares(void **initrd, size_t *initrd_size); +>>>>>>> main #endif diff --git a/scripts/ubuntu/initramfs-tools b/scripts/ubuntu/initramfs-tools new file mode 100644 index 0000000..f62f02e --- /dev/null +++ b/scripts/ubuntu/initramfs-tools @@ -0,0 +1,14 @@ +if [ "${PS5_FW_INSTALL_DONE:-}" != y ] && + [ -f /scripts/functions ] && + [ -d /scripts/local-bottom ] && + [ -n "$rootmnt" ] && + [ -e "${rootmnt}/etc/os-release" ]; then + ID= + ID_LIKE= + . "${rootmnt}/etc/os-release" + case " ${ID} ${ID_LIKE} " in + *" ubuntu "*) + [ -e /scripts/ubuntu/ps5-wifi-fw ] && . /scripts/ubuntu/ps5-wifi-fw + ;; + esac +fi diff --git a/scripts/ubuntu/ps5-wifi-fw b/scripts/ubuntu/ps5-wifi-fw new file mode 100644 index 0000000..b5411a0 --- /dev/null +++ b/scripts/ubuntu/ps5-wifi-fw @@ -0,0 +1,13 @@ +if [ "${PS5_FW_INSTALL_DONE:-}" != y ]; then + FW_PATH="usr/lib/firmware/nxp/pcieuartiw620_combo_v1.bin" + FW_SRC="/${FW_PATH}" + FW_DST="${rootmnt}/${FW_PATH}" + if [ -n "$rootmnt" ] && [ -f "$FW_SRC" ]; then + mkdir -p "${FW_DST%/*}" + cp "$FW_SRC" "$FW_DST" + chmod 0644 "$FW_DST" + PS5_FW_INSTALL_DONE=y + export PS5_FW_INSTALL_DONE + [ -e /dev/kmsg ] && printf 'ps5-fw-install: installed %s\n' "$FW_DST" > /dev/kmsg || true + fi +fi diff --git a/source/cpio.c b/source/cpio.c new file mode 100644 index 0000000..aa66ffc --- /dev/null +++ b/source/cpio.c @@ -0,0 +1,74 @@ +#include "cpio.h" +#include +#include + +#define CPIO_NEWC_HEADER_LEN 110 + +static size_t cpio_newc_align4(size_t n) { return (n + 3) & ~3ULL; } + +size_t cpio_newc_entry_size(const char *name, size_t data_size) { + return cpio_newc_align4(CPIO_NEWC_HEADER_LEN + strlen(name) + 1) + + cpio_newc_align4(data_size); +} + +uint8_t *cpio_newc_data(uint8_t *entry, const char *name) { + return (uint8_t *)cpio_newc_align4((uintptr_t)entry + CPIO_NEWC_HEADER_LEN + + strlen(name) + 1); +} + +uint8_t *cpio_newc_write_entry(uint8_t *out, const char *name, uint32_t mode, + const void *data, size_t data_size, + uint32_t ino) { + size_t name_size = strlen(name) + 1; + + out = (uint8_t *)cpio_newc_align4((uintptr_t)out); + + sprintf((char *)out, + "070701%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X", + ino, mode, 0, 0, 1, 0, (uint32_t)data_size, 0, 0, 0, 0, + (uint32_t)name_size, 0); + out += CPIO_NEWC_HEADER_LEN; + + memcpy(out, name, name_size); + out += name_size; + out = (uint8_t *)cpio_newc_align4((uintptr_t)out); + + if (data_size != 0 && data != out) { + memcpy(out, data, data_size); + } + out += data_size; + out = (uint8_t *)cpio_newc_align4((uintptr_t)out); + + return out; +} + +size_t cpio_newc_parent_dirs_size(const char *path) { + char tmp[256]; + size_t total = 0; + + snprintf(tmp, sizeof(tmp), "%s", path); + for (char *p = strchr(tmp, '/'); p != NULL; p = strchr(p + 1, '/')) { + *p = '\0'; + if (tmp[0] != '\0') + total += cpio_newc_entry_size(tmp, 0); + *p = '/'; + } + + return total; +} + +uint8_t *cpio_newc_write_parent_dirs(uint8_t *out, const char *path, + uint32_t *ino) { + char tmp[256]; + + snprintf(tmp, sizeof(tmp), "%s", path); + for (char *p = strchr(tmp, '/'); p != NULL; p = strchr(p + 1, '/')) { + *p = '\0'; + if (tmp[0] != '\0') { + out = cpio_newc_write_entry(out, tmp, CPIO_MODE_DIR, NULL, 0, (*ino)++); + } + *p = '/'; + } + + return out; +}