Index | Thread | Search

From:
Hans-Jörg Höxer <hshoexer@genua.de>
Subject:
psp(4): Download firmware command 2/3
To:
<tech@openbsd.org>
Date:
Fri, 25 Oct 2024 15:50:15 +0200

Download raw body.

Thread
Hi,

this implements the download firmware command.

Take care,
HJ.
-------------------------------------------------------------------
commit eec4dc462c8ba317902623b7ac11e4dd9f598969
Author: Hans-Joerg Hoexer <hshoexer@genua.de>
Date:   Mon Oct 21 14:26:48 2024 +0200

    psp(4): Download firmware command
    
    Implement the download firmware command.  Will be used by automatic
    firmware loading.

diff --git a/sys/dev/ic/psp.c b/sys/dev/ic/psp.c
index eebae8bab57..92459c9e06f 100644
--- a/sys/dev/ic/psp.c
+++ b/sys/dev/ic/psp.c
@@ -603,6 +603,55 @@ psp_deactivate(struct psp_softc *sc, struct psp_deactivate *udeact)
 	return (0);
 }
 
+int
+psp_downloadfirmware(struct psp_softc *sc, struct psp_downloadfirmware *udlfw)
+{
+	struct psp_downloadfirmware *dlfw;
+	bus_dmamap_t		 map;
+	bus_dma_segment_t	 seg;
+	caddr_t			 kva;
+	int			 nsegs;
+	int			 ret;
+
+	dlfw = (struct psp_downloadfirmware *)sc->sc_cmd_kva;
+	bzero(dlfw, sizeof(*dlfw));
+
+	ret = ENOMEM;
+	if (bus_dmamap_create(sc->sc_dmat, udlfw->fw_len, 1, udlfw->fw_len, 0,
+	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, &map) != 0)
+		return (ret);
+	if (bus_dmamem_alloc(sc->sc_dmat, udlfw->fw_len, 0, 0, &seg, 1,
+	    &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0 || nsegs != 1)
+		goto fail_0;
+	if (bus_dmamem_map(sc->sc_dmat, &seg, nsegs, udlfw->fw_len, &kva,
+	    BUS_DMA_WAITOK) != 0)
+		goto fail_1;
+	if (bus_dmamap_load(sc->sc_dmat, map, kva, udlfw->fw_len, NULL,
+	    BUS_DMA_WAITOK) != 0)
+		goto fail_2;
+
+	bcopy((void *)udlfw->fw_paddr, kva, udlfw->fw_len);
+
+	dlfw->fw_paddr = map->dm_segs[0].ds_addr;
+	dlfw->fw_len = map->dm_segs[0].ds_len;
+
+	ret = ccp_docmd(sc, PSP_CMD_DOWNLOADFIRMWARE,
+	    sc->sc_cmd_map->dm_segs[0].ds_addr);
+
+	if (ret != 0)
+		ret = EIO;
+
+	bus_dmamap_unload(sc->sc_dmat, map);
+fail_2:
+	bus_dmamem_unmap(sc->sc_dmat, kva, udlfw->fw_len);
+fail_1:
+	bus_dmamem_free(sc->sc_dmat, &seg, 1);
+fail_0:
+	bus_dmamap_destroy(sc->sc_dmat, map);
+
+	return (ret);
+}
+
 int
 psp_guest_shutdown(struct psp_softc *sc, struct psp_guest_shutdown *ugshutdown)
 {
diff --git a/sys/dev/ic/pspvar.h b/sys/dev/ic/pspvar.h
index e7c776ea0cf..888b5d95daa 100644
--- a/sys/dev/ic/pspvar.h
+++ b/sys/dev/ic/pspvar.h
@@ -78,6 +78,7 @@
 #define PSP_CMD_INIT			0x1
 #define PSP_CMD_PLATFORMSTATUS		0x4
 #define PSP_CMD_DF_FLUSH		0xa
+#define PSP_CMD_DOWNLOADFIRMWARE	0xb
 #define PSP_CMD_DECOMMISSION		0x20
 #define PSP_CMD_ACTIVATE		0x21
 #define PSP_CMD_DEACTIVATE		0x22
@@ -214,6 +215,11 @@ struct psp_init {
 	uint32_t		tmr_length;
 } __packed;
 
+struct psp_downloadfirmware {
+	/* Input parameters for PSP_CMD_DOWNLOADFIRMWARE */
+	uint64_t		fw_paddr;
+	uint32_t		fw_len;
+} __packed;
 
 struct psp_guest_shutdown {
 	/* Input parameter for PSP_CMD_GUEST_SHUTDOWN */