Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpu/drm/nouveau/nvkm/subdev/fsp/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  gh100.c   Sprache: C

 
/* SPDX-License-Identifier: MIT
 *
 * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
 */

#include "priv.h"

#include <nvhw/drf.h>
#include <nvhw/ref/gh100/dev_fsp_pri.h>
#include <nvhw/ref/gh100/dev_therm.h>

#include <nvrm/nvtypes.h>

#define MCTP_HEADER_VERSION          3:0
#define MCTP_HEADER_RSVD             7:4

#define MCTP_HEADER_DEID            15:8
#define MCTP_HEADER_SEID            23:16

#define MCTP_HEADER_TAG             26:24
#define MCTP_HEADER_TO              27:27
#define MCTP_HEADER_SEQ             29:28
#define MCTP_HEADER_EOM             30:30
#define MCTP_HEADER_SOM             31:31

#define MCTP_MSG_HEADER_TYPE         6:0
#define MCTP_MSG_HEADER_IC           7:7

#define MCTP_MSG_HEADER_VENDOR_ID   23:8
#define MCTP_MSG_HEADER_NVDM_TYPE   31:24

#define MCTP_MSG_HEADER_TYPE_VENDOR_PCI 0x7e
#define MCTP_MSG_HEADER_VENDOR_ID_NV    0x10de

#define NVDM_TYPE_COT                   0x14
#define NVDM_TYPE_FSP_RESPONSE          0x15

#pragma pack(1)
typedef struct nvdm_payload_cot
{
    NvU16 version;
    NvU16 size;
    NvU64 gspFmcSysmemOffset;
    NvU64 frtsSysmemOffset;
    NvU32 frtsSysmemSize;

    // Note this is an offset from the end of FB
    NvU64 frtsVidmemOffset;
    NvU32 frtsVidmemSize;

    // Authentication related fields
    NvU32 hash384[12];
    NvU32 publicKey[96];
    NvU32 signature[96];

    NvU64 gspBootArgsSysmemOffset;
} NVDM_PAYLOAD_COT;
#pragma pack()

#pragma pack(1)
typedef struct
{
    NvU32 taskId;
    NvU32 commandNvdmType;
    NvU32 errorCode;
} NVDM_PAYLOAD_COMMAND_RESPONSE;
#pragma pack()

static u32
gh100_fsp_poll(struct nvkm_fsp *fsp)
{
 struct nvkm_device *device = fsp->subdev.device;
 u32 head, tail;

 head = nvkm_rd32(device, NV_PFSP_MSGQ_HEAD(0));
 tail = nvkm_rd32(device, NV_PFSP_MSGQ_TAIL(0));

 if (head == tail)
  return 0;

 return (tail - head) + sizeof(u32); /* TAIL points at last DWORD written. */
}

static int
gh100_fsp_recv(struct nvkm_fsp *fsp, u8 *packet, u32 max_packet_size)
{
 struct nvkm_device *device = fsp->subdev.device;
 u32 packet_size;
 int ret;

 packet_size = gh100_fsp_poll(fsp);
 if (!packet_size || WARN_ON(packet_size % 4 || packet_size > max_packet_size))
  return -EINVAL;

 ret = nvkm_falcon_pio_rd(&fsp->falcon, 0, EMEM, 0, packet, 0, packet_size);
 if (ret)
  return ret;

 nvkm_wr32(device, NV_PFSP_MSGQ_TAIL(0), 0);
 nvkm_wr32(device, NV_PFSP_MSGQ_HEAD(0), 0);

 return packet_size;
}

static int
gh100_fsp_wait(struct nvkm_fsp *fsp)
{
 int time = 1000;

 do {
  if (gh100_fsp_poll(fsp))
   return 0;

  usleep_range(1000, 2000);
 } while(time--);

 return -ETIMEDOUT;
}

static int
gh100_fsp_send(struct nvkm_fsp *fsp, const u8 *packet, u32 packet_size)
{
 struct nvkm_device *device = fsp->subdev.device;
 int time = 1000, ret;

 if (WARN_ON(packet_size % sizeof(u32)))
  return -EINVAL;

 /* Ensure any previously sent message has been consumed. */
 do {
  u32 head = nvkm_rd32(device, NV_PFSP_QUEUE_HEAD(0));
  u32 tail = nvkm_rd32(device, NV_PFSP_QUEUE_TAIL(0));

  if (tail == head)
   break;

  usleep_range(1000, 2000);
 } while(time--);

 if (time < 0)
  return -ETIMEDOUT;

 /* Write message to EMEM. */
 ret = nvkm_falcon_pio_wr(&fsp->falcon, packet, 0, 0, EMEM, 0, packet_size, 0, false);
 if (ret)
  return ret;

 /* Update queue pointers - TAIL points at last DWORD written. */
 nvkm_wr32(device, NV_PFSP_QUEUE_TAIL(0), packet_size - sizeof(u32));
 nvkm_wr32(device, NV_PFSP_QUEUE_HEAD(0), 0);
 return 0;
}

static int
gh100_fsp_send_sync(struct nvkm_fsp *fsp, u8 nvdm_type, const u8 *packet, u32 packet_size)
{
 struct nvkm_subdev *subdev = &fsp->subdev;
 struct {
  u32 mctp_header;
  u32 nvdm_header;
  NVDM_PAYLOAD_COMMAND_RESPONSE response;
 } reply;
 int ret;

 ret = gh100_fsp_send(fsp, packet, packet_size);
 if (ret)
  return ret;

 ret = gh100_fsp_wait(fsp);
 if (ret)
  return ret;

 ret = gh100_fsp_recv(fsp, (u8 *)&reply, sizeof(reply));
 if (ret < 0)
  return ret;

 if (NVVAL_TEST(reply.mctp_header, MCTP, HEADER, SOM, !=, 1) ||
     NVVAL_TEST(reply.mctp_header, MCTP, HEADER, EOM, !=, 1)) {
  nvkm_error(subdev, "unexpected MCTP header in reply: 0x%08x\n", reply.mctp_header);
  return -EIO;
 }

 if (NVDEF_TEST(reply.nvdm_header, MCTP, MSG_HEADER, TYPE, !=, VENDOR_PCI) ||
     NVDEF_TEST(reply.nvdm_header, MCTP, MSG_HEADER, VENDOR_ID, !=, NV) ||
     NVVAL_TEST(reply.nvdm_header, MCTP, MSG_HEADER, NVDM_TYPE, !=, NVDM_TYPE_FSP_RESPONSE)) {
  nvkm_error(subdev, "unexpected NVDM header in reply: 0x%08x\n", reply.nvdm_header);
  return -EIO;
 }

 if (reply.response.commandNvdmType != nvdm_type) {
  nvkm_error(subdev, "expected NVDM type 0x%02x in reply, got 0x%02x\n",
      nvdm_type, reply.response.commandNvdmType);
  return -EIO;
 }

 if (reply.response.errorCode) {
  nvkm_error(subdev, "NVDM command 0x%02x failed with error 0x%08x\n",
      nvdm_type, reply.response.errorCode);
  return -EIO;
 }

 return 0;
}

int
gh100_fsp_boot_gsp_fmc(struct nvkm_fsp *fsp, u64 args_addr, u32 rsvd_size, bool resume,
         u64 img_addr, const u8 *hash, const u8 *pkey, const u8 *sig)
{
 struct {
  u32 mctp_header;
  u32 nvdm_header;
  NVDM_PAYLOAD_COT cot;
 } msg = {};

 msg.mctp_header = NVVAL(MCTP, HEADER, SOM, 1) |
     NVVAL(MCTP, HEADER, EOM, 1) |
     NVVAL(MCTP, HEADER, SEID, 0) |
     NVVAL(MCTP, HEADER, SEQ, 0);

 msg.nvdm_header = NVDEF(MCTP, MSG_HEADER, TYPE, VENDOR_PCI) |
     NVDEF(MCTP, MSG_HEADER, VENDOR_ID, NV) |
     NVVAL(MCTP, MSG_HEADER, NVDM_TYPE, NVDM_TYPE_COT);

 msg.cot.version = fsp->func->cot.version;
 msg.cot.size = sizeof(msg.cot);
 msg.cot.gspFmcSysmemOffset = img_addr;
 if (!resume) {
  msg.cot.frtsVidmemOffset = ALIGN(rsvd_size, 0x200000);
  msg.cot.frtsVidmemSize = 0x100000;
 }

 memcpy(msg.cot.hash384, hash, fsp->func->cot.size_hash);
 memcpy(msg.cot.publicKey, pkey, fsp->func->cot.size_pkey);
 memcpy(msg.cot.signature, sig, fsp->func->cot.size_sig);

 msg.cot.gspBootArgsSysmemOffset = args_addr;

 return gh100_fsp_send_sync(fsp, NVDM_TYPE_COT, (const u8 *)&msg, sizeof(msg));
}

int
gh100_fsp_wait_secure_boot(struct nvkm_fsp *fsp)
{
 struct nvkm_device *device = fsp->subdev.device;
 unsigned timeout_ms = 4000;

 do {
  u32 status = NVKM_RD32(device, NV_THERM, I2CS_SCRATCH, FSP_BOOT_COMPLETE_STATUS);

  if (status == NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS_SUCCESS)
   return 0;

  usleep_range(1000, 2000);
 } while (timeout_ms--);

 return -ETIMEDOUT;
}

static const struct nvkm_fsp_func
gh100_fsp = {
 .wait_secure_boot = gh100_fsp_wait_secure_boot,
 .cot = {
  .version = 1,
  .size_hash = 48,
  .size_pkey = 384,
  .size_sig = 384,
  .boot_gsp_fmc = gh100_fsp_boot_gsp_fmc,
 },
};

int
gh100_fsp_new(struct nvkm_device *device,
       enum nvkm_subdev_type type, int inst, struct nvkm_fsp **pfsp)
{
 return nvkm_fsp_new_(&gh100_fsp, device, type, inst, pfsp);
}

Messung V0.5
C=98 H=89 G=93

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.