From: uverma@linux.ibm.com
To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org, aik@ozlabs.ru
Cc: pbonzini@redhat.com, th.huth@posteo.eu, nnmlinux@linux.ibm.com,
sbhat@linux.ibm.com, harshpb@linux.ibm.com,
amachhiw@linux.ibm.com, rathc@linux.ibm.com, balaton@eik.bme.hu,
philmd@oss.qualcomm.com, npiggin@gmail.com,
marcandre.lureau@redhat.com, fam@euphon.net,
Utkarsh Verma <uverma@linux.ibm.com>
Subject: [RFC PATCH 1/8] ppc/spapr: add PReP boot partition detection
Date: Mon, 17 Aug 2026 15:57:18 +0530 [thread overview]
Message-ID: <20260817102733.605346-2-uverma@linux.ibm.com> (raw)
In-Reply-To: <20260817102733.605346-1-uverma@linux.ibm.com>
From: Utkarsh Verma <uverma@linux.ibm.com>
Add spapr_vof_partition.c which implements basic MBR and GPT partition
table scanning to locate the PReP boot partition during VOF enabled boot.
AI-used-for: code
Signed-off-by: Utkarsh Verma <uverma@linux.ibm.com>
---
hw/ppc/meson.build | 5 +-
hw/ppc/spapr_vof_partition.c | 176 +++++++++++++++++++++++++++++++++++
include/hw/ppc/spapr_vof.h | 14 +++
3 files changed, 194 insertions(+), 1 deletion(-)
create mode 100644 hw/ppc/spapr_vof_partition.c
create mode 100644 include/hw/ppc/spapr_vof.h
diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index 37aa535db2..68a5d2622f 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -93,6 +93,9 @@ ppc_ss.add(when: 'CONFIG_AMIGAONE', if_true: files('amigaone.c'))
ppc_ss.add(when: 'CONFIG_PEGASOS', if_true: files('pegasos.c'))
ppc_ss.add(when: 'CONFIG_VOF', if_true: files('vof.c'))
-ppc_ss.add(when: ['CONFIG_VOF', 'CONFIG_PSERIES'], if_true: files('spapr_vof.c'))
+ppc_ss.add(when: ['CONFIG_VOF', 'CONFIG_PSERIES'], if_true: files(
+ 'spapr_vof.c',
+ 'spapr_vof_partition.c',
+))
hw_arch += {'ppc': ppc_ss}
diff --git a/hw/ppc/spapr_vof_partition.c b/hw/ppc/spapr_vof_partition.c
new file mode 100644
index 0000000000..ced2818998
--- /dev/null
+++ b/hw/ppc/spapr_vof_partition.c
@@ -0,0 +1,176 @@
+/*
+ * QEMU PowerPC sPAPR VOF Partition Table Support.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This implements partition table detection for VOF boot,
+ * supporting MBR and GPT partition tables with focus on PReP boot partition.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bswap.h"
+#include "qemu/error-report.h"
+#include "system/block-backend-io.h"
+#include "hw/ppc/spapr_vof.h"
+
+#define SECTOR_SIZE 512
+#define MBR_PARTITION_ENTRY_SIZE 16
+#define MBR_PARTITION_TABLE_OFFSET 446
+#define MBR_NUM_PARTITIONS 4
+
+#define PARTITION_TYPE_PREP 0x41 /* PReP Boot partition */
+#define PARTITION_TYPE_GPT 0xEE
+
+#define GPT_SIGNATURE "EFI PART"
+#define GPT_SIGNATURE_SIZE 8
+
+/* PReP Boot: 9E1A2D38-C612-4316-AA26-8B49521E5A8B */
+static const uint8_t GUID_PREP_BOOT[16] = {
+ 0x38, 0x2D, 0x1A, 0x9E, 0x12, 0xC6, 0x16, 0x43,
+ 0xAA, 0x26, 0x8B, 0x49, 0x52, 0x1E, 0x5A, 0x8B
+};
+
+typedef struct MBRPartitionEntry {
+ uint8_t boot_flag;
+ uint8_t start_chs[3];
+ uint8_t type;
+ uint8_t end_chs[3];
+ uint32_t start_lba;
+ uint32_t num_sectors;
+} QEMU_PACKED MBRPartitionEntry;
+
+typedef struct GPTHeader {
+ char signature[8];
+ uint32_t revision;
+ uint32_t header_size;
+ uint32_t header_crc32;
+ uint32_t reserved;
+ uint64_t current_lba;
+ uint64_t backup_lba;
+ uint64_t first_usable_lba;
+ uint64_t last_usable_lba;
+ uint8_t disk_guid[16];
+ uint64_t partition_entries_lba;
+ uint32_t num_partition_entries;
+ uint32_t partition_entry_size;
+ uint32_t partition_array_crc32;
+} QEMU_PACKED GPTHeader;
+
+typedef struct GPTPartitionEntry {
+ uint8_t type_guid[16];
+ uint8_t partition_guid[16];
+ uint64_t first_lba;
+ uint64_t last_lba;
+ uint64_t attributes;
+ uint16_t name[36];
+} QEMU_PACKED GPTPartitionEntry;
+
+static bool find_prep_partition_gpt(BlockBackend *blk,
+ uint64_t *offset, uint64_t *size)
+{
+ uint8_t lba1[SECTOR_SIZE];
+ GPTHeader *header;
+ uint64_t entries_lba;
+ uint32_t num_entries;
+ uint32_t entry_size;
+ uint64_t current_entry_offset;
+ uint8_t *buf;
+ GPTPartitionEntry *current_entry;
+ uint32_t i;
+ int ret;
+
+ ret = blk_pread(blk, SECTOR_SIZE, SECTOR_SIZE, lba1, 0);
+ if (ret < 0) {
+ warn_report("GPT: failed to read LBA1 (ret=%d)", ret);
+ return false;
+ }
+
+ header = (GPTHeader *)lba1;
+
+ if (memcmp(header->signature, GPT_SIGNATURE, GPT_SIGNATURE_SIZE) != 0) {
+ return false;
+ }
+
+ entries_lba = le64_to_cpu(header->partition_entries_lba);
+ num_entries = le32_to_cpu(header->num_partition_entries);
+ entry_size = le32_to_cpu(header->partition_entry_size);
+
+ if (num_entries > 128) {
+ num_entries = 128;
+ }
+
+ if (entry_size < 128) {
+ return false;
+ }
+
+ buf = g_malloc(entry_size);
+ for (i = 0; i < num_entries; i++) {
+ current_entry_offset = (entries_lba * SECTOR_SIZE) +
+ ((uint64_t)i * entry_size);
+
+ ret = blk_pread(blk, current_entry_offset, entry_size, buf, 0);
+ if (ret < 0) {
+ warn_report("GPT: failed to read partition entry %u "
+ "(ret=%d)", i, ret);
+ g_free(buf);
+ return false;
+ }
+
+ current_entry = (GPTPartitionEntry *)buf;
+ if (memcmp(current_entry->type_guid, GUID_PREP_BOOT,
+ sizeof(GUID_PREP_BOOT)) == 0) {
+ *offset = le64_to_cpu(current_entry->first_lba) * SECTOR_SIZE;
+ *size = (le64_to_cpu(current_entry->last_lba) -
+ le64_to_cpu(current_entry->first_lba) + 1) * SECTOR_SIZE;
+ g_free(buf);
+ return true;
+ }
+ }
+ g_free(buf);
+ return false;
+}
+
+static bool find_prep_partition_mbr(BlockBackend *blk,
+ uint64_t *offset, uint64_t *size)
+{
+ uint8_t mbr[SECTOR_SIZE];
+ MBRPartitionEntry *entry;
+ int ret;
+ int i;
+
+ ret = blk_pread(blk, 0, SECTOR_SIZE, mbr, 0);
+ if (ret < 0) {
+ warn_report("MBR: failed to read MBR sector (ret=%d)", ret);
+ return false;
+ }
+
+ /* MBR boot signature: byte 510 = 0x55, byte 511 = 0xAA */
+ if (mbr[510] != 0x55 || mbr[511] != 0xAA) {
+ return false;
+ }
+
+ for (i = 0; i < MBR_NUM_PARTITIONS; i++) {
+ entry = (MBRPartitionEntry *)&mbr[MBR_PARTITION_TABLE_OFFSET +
+ i * MBR_PARTITION_ENTRY_SIZE];
+
+ if (entry->type == PARTITION_TYPE_GPT) {
+ return find_prep_partition_gpt(blk, offset, size);
+ }
+
+ if (entry->type == PARTITION_TYPE_PREP) {
+ *offset = (uint64_t)le32_to_cpu(entry->start_lba) * SECTOR_SIZE;
+ *size = (uint64_t)le32_to_cpu(entry->num_sectors) * SECTOR_SIZE;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool spapr_vof_find_prep_partition(BlockBackend *blk,
+ uint64_t *offset, uint64_t *size)
+{
+ if (!blk) {
+ return false;
+ }
+ return find_prep_partition_mbr(blk, offset, size);
+}
diff --git a/include/hw/ppc/spapr_vof.h b/include/hw/ppc/spapr_vof.h
new file mode 100644
index 0000000000..08787d2aeb
--- /dev/null
+++ b/include/hw/ppc/spapr_vof.h
@@ -0,0 +1,14 @@
+/*
+ * QEMU PowerPC sPAPR VOF Support
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef HW_SPAPR_VOF_H
+#define HW_SPAPR_VOF_H
+
+typedef struct BlockBackend BlockBackend;
+
+bool spapr_vof_find_prep_partition(BlockBackend *blk,
+ uint64_t *offset, uint64_t *size);
+
+#endif /* HW_SPAPR_VOF_H */
--
2.54.0
next prev parent reply other threads:[~2026-08-17 10:29 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-17 10:27 [RFC PATCH 0/8] ppc/spapr: VOF disk image (qcow2) boot support uverma
2026-08-17 10:27 ` uverma [this message]
2026-08-17 10:27 ` [RFC PATCH 2/8] hw/loader: add load_elf_ram_sym_buf() for in-memory ELF loading uverma
2026-08-17 10:27 ` [RFC PATCH 3/8] ppc/spapr: add baseline VOF disk boot support uverma
2026-08-17 10:27 ` [RFC PATCH 4/8] ppc/spapr: add VTY backend support to OF read/write/open services uverma
2026-08-17 10:27 ` [RFC PATCH 5/8] ppc/spapr: add block device backend to VOF open/read/write/seek services uverma
2026-08-17 10:27 ` [RFC PATCH 6/8] spapr_vscsi: add VOF disk nodes to the device tree uverma
2026-08-17 10:27 ` [RFC PATCH 7/8] ppc/spapr: strip OF path argument suffix in path_offset uverma
2026-08-17 10:27 ` [RFC PATCH 8/8] ppc/spapr: implement vscsi-report-luns call-method for PAPR vSCSI uverma
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260817102733.605346-2-uverma@linux.ibm.com \
--to=uverma@linux.ibm.com \
--cc=aik@ozlabs.ru \
--cc=amachhiw@linux.ibm.com \
--cc=balaton@eik.bme.hu \
--cc=fam@euphon.net \
--cc=harshpb@linux.ibm.com \
--cc=marcandre.lureau@redhat.com \
--cc=nnmlinux@linux.ibm.com \
--cc=npiggin@gmail.com \
--cc=pbonzini@redhat.com \
--cc=philmd@oss.qualcomm.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
--cc=rathc@linux.ibm.com \
--cc=sbhat@linux.ibm.com \
--cc=th.huth@posteo.eu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.