mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-14 09:14:40 +00:00
nvme: Check the return code of the admin passthru ioctl
This meant we reported firmware update success when the image format or offset was incorrect.
This commit is contained in:
parent
18f3ab4e4d
commit
fa8b7aab0a
140
plugins/nvme/fu-nvme-common.c
Normal file
140
plugins/nvme/fu-nvme-common.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "fu-nvme-common.h"
|
||||
|
||||
const gchar *
|
||||
fu_nvme_status_to_string (guint32 status)
|
||||
{
|
||||
switch (status) {
|
||||
case NVME_SC_SUCCESS:
|
||||
return "Command completed successfully";
|
||||
case NVME_SC_INVALID_OPCODE:
|
||||
return "Associated command opcode field is not valid";
|
||||
case NVME_SC_INVALID_FIELD:
|
||||
return "Unsupported value in a defined field";
|
||||
case NVME_SC_CMDID_CONFLICT:
|
||||
return "Command identifier is already in use";
|
||||
case NVME_SC_DATA_XFER_ERROR:
|
||||
return "Error while trying to transfer the data or metadata";
|
||||
case NVME_SC_POWER_LOSS:
|
||||
return "Command aborted due to power loss notification";
|
||||
case NVME_SC_INTERNAL:
|
||||
return "Internal error";
|
||||
case NVME_SC_ABORT_REQ:
|
||||
return "Command Abort request";
|
||||
case NVME_SC_ABORT_QUEUE:
|
||||
return "Delete I/O Submission Queue request";
|
||||
case NVME_SC_FUSED_FAIL:
|
||||
return "Other command in a fused operation failing";
|
||||
case NVME_SC_FUSED_MISSING:
|
||||
return "Missing Fused Command";
|
||||
case NVME_SC_INVALID_NS:
|
||||
return "Namespace or the format of that namespace is invalid";
|
||||
case NVME_SC_CMD_SEQ_ERROR:
|
||||
return "Protocol violation in a multicommand sequence";
|
||||
case NVME_SC_SANITIZE_FAILED:
|
||||
return "No recovery actions has been successfully completed";
|
||||
case NVME_SC_SANITIZE_IN_PROGRESS:
|
||||
return "A sanitize operation is in progress";
|
||||
case NVME_SC_LBA_RANGE:
|
||||
return "LBA exceeds the size of the namespace";
|
||||
case NVME_SC_NS_WRITE_PROTECTED:
|
||||
return "Namespace is write protected by the host";
|
||||
case NVME_SC_CAP_EXCEEDED:
|
||||
return "Capacity of the namespace to be exceeded";
|
||||
case NVME_SC_NS_NOT_READY:
|
||||
return "Namespace is not ready to be accessed";
|
||||
case NVME_SC_RESERVATION_CONFLICT:
|
||||
return "Conflict with a reservation on the accessed namespace";
|
||||
case NVME_SC_CQ_INVALID:
|
||||
return "Completion Queue does not exist";
|
||||
case NVME_SC_QID_INVALID:
|
||||
return "Invalid queue identifier specified";
|
||||
case NVME_SC_QUEUE_SIZE:
|
||||
return "Invalid queue size";
|
||||
case NVME_SC_ABORT_LIMIT:
|
||||
return "Outstanding Abort commands has exceeded the limit";
|
||||
case NVME_SC_ABORT_MISSING:
|
||||
return "Abort command is missing";
|
||||
case NVME_SC_ASYNC_LIMIT:
|
||||
return "Outstanding Async commands has been exceeded";
|
||||
case NVME_SC_FIRMWARE_SLOT:
|
||||
return "Slot is invalid or read only";
|
||||
case NVME_SC_FIRMWARE_IMAGE:
|
||||
return "Image specified for activation is invalid";
|
||||
case NVME_SC_INVALID_VECTOR:
|
||||
return "Creation failed due to an invalid interrupt vector";
|
||||
case NVME_SC_INVALID_LOG_PAGE:
|
||||
return "Log page indicated is invalid";
|
||||
case NVME_SC_INVALID_FORMAT:
|
||||
return "LBA Format specified is not supported";
|
||||
case NVME_SC_FW_NEEDS_CONV_RESET:
|
||||
return "commit was successful, but activation requires reset";
|
||||
case NVME_SC_INVALID_QUEUE:
|
||||
return "Failed to delete the I/O Completion Queue specified";
|
||||
case NVME_SC_FEATURE_NOT_SAVEABLE:
|
||||
return "Feature Identifier does not support a saveable value";
|
||||
case NVME_SC_FEATURE_NOT_CHANGEABLE:
|
||||
return "Feature Identifier is not able to be changed";
|
||||
case NVME_SC_FEATURE_NOT_PER_NS:
|
||||
return "Feature Identifier specified is not namespace specific";
|
||||
case NVME_SC_FW_NEEDS_SUBSYS_RESET:
|
||||
return "Commit was successful, activation requires NVM Subsystem";
|
||||
case NVME_SC_FW_NEEDS_RESET:
|
||||
return "Commit was successful, activation requires a reset";
|
||||
case NVME_SC_FW_NEEDS_MAX_TIME:
|
||||
return "Would exceed the Maximum Time for Firmware Activation";
|
||||
case NVME_SC_FW_ACIVATE_PROHIBITED:
|
||||
return "Image specified is being prohibited from activation";
|
||||
case NVME_SC_OVERLAPPING_RANGE:
|
||||
return "Image has overlapping ranges";
|
||||
case NVME_SC_NS_INSUFFICENT_CAP:
|
||||
return "Requires more free space than is currently available";
|
||||
case NVME_SC_NS_ID_UNAVAILABLE:
|
||||
return "Number of namespaces supported has been exceeded";
|
||||
case NVME_SC_NS_ALREADY_ATTACHED:
|
||||
return "Controller is already attached to the namespace";
|
||||
case NVME_SC_NS_IS_PRIVATE:
|
||||
return "Namespace is private";
|
||||
case NVME_SC_NS_NOT_ATTACHED:
|
||||
return "Controller is not attached to the namespace";
|
||||
case NVME_SC_THIN_PROV_NOT_SUPP:
|
||||
return "Thin provisioning is not supported by the controller";
|
||||
case NVME_SC_CTRL_LIST_INVALID:
|
||||
return "Controller list provided is invalid";
|
||||
case NVME_SC_BP_WRITE_PROHIBITED:
|
||||
return "Trying to modify a Boot Partition while it is locked";
|
||||
case NVME_SC_BAD_ATTRIBUTES:
|
||||
return "Bad attributes";
|
||||
case NVME_SC_WRITE_FAULT:
|
||||
return "Write data could not be committed to the media";
|
||||
case NVME_SC_READ_ERROR:
|
||||
return "Read data could not be recovered from the media";
|
||||
case NVME_SC_GUARD_CHECK:
|
||||
return "End-to-end guard check failure";
|
||||
case NVME_SC_APPTAG_CHECK:
|
||||
return "End-to-end application tag check failure";
|
||||
case NVME_SC_REFTAG_CHECK:
|
||||
return "End-to-end reference tag check failure";
|
||||
case NVME_SC_COMPARE_FAILED:
|
||||
return "Miscompare during a Compare command";
|
||||
case NVME_SC_ACCESS_DENIED:
|
||||
return "Access denied";
|
||||
case NVME_SC_UNWRITTEN_BLOCK:
|
||||
return "Read from an LBA range containing a unwritten block";
|
||||
case NVME_SC_ANA_PERSISTENT_LOSS:
|
||||
return "Namespace is in the ANA Persistent Loss state";
|
||||
case NVME_SC_ANA_INACCESSIBLE:
|
||||
return "Namespace being in the ANA Inaccessible state";
|
||||
case NVME_SC_ANA_TRANSITION:
|
||||
return "Namespace transitioning between Async Access states";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
129
plugins/nvme/fu-nvme-common.h
Normal file
129
plugins/nvme/fu-nvme-common.h
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#ifndef __FU_NVME_COMMON_H
|
||||
#define __FU_NVME_COMMON_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
enum {
|
||||
/*
|
||||
* Generic Command Status:
|
||||
*/
|
||||
NVME_SC_SUCCESS = 0x0,
|
||||
NVME_SC_INVALID_OPCODE = 0x1,
|
||||
NVME_SC_INVALID_FIELD = 0x2,
|
||||
NVME_SC_CMDID_CONFLICT = 0x3,
|
||||
NVME_SC_DATA_XFER_ERROR = 0x4,
|
||||
NVME_SC_POWER_LOSS = 0x5,
|
||||
NVME_SC_INTERNAL = 0x6,
|
||||
NVME_SC_ABORT_REQ = 0x7,
|
||||
NVME_SC_ABORT_QUEUE = 0x8,
|
||||
NVME_SC_FUSED_FAIL = 0x9,
|
||||
NVME_SC_FUSED_MISSING = 0xa,
|
||||
NVME_SC_INVALID_NS = 0xb,
|
||||
NVME_SC_CMD_SEQ_ERROR = 0xc,
|
||||
NVME_SC_SGL_INVALID_LAST = 0xd,
|
||||
NVME_SC_SGL_INVALID_COUNT = 0xe,
|
||||
NVME_SC_SGL_INVALID_DATA = 0xf,
|
||||
NVME_SC_SGL_INVALID_METADATA = 0x10,
|
||||
NVME_SC_SGL_INVALID_TYPE = 0x11,
|
||||
|
||||
NVME_SC_SGL_INVALID_OFFSET = 0x16,
|
||||
NVME_SC_SGL_INVALID_SUBTYPE = 0x17,
|
||||
|
||||
NVME_SC_SANITIZE_FAILED = 0x1C,
|
||||
NVME_SC_SANITIZE_IN_PROGRESS = 0x1D,
|
||||
|
||||
NVME_SC_NS_WRITE_PROTECTED = 0x20,
|
||||
|
||||
NVME_SC_LBA_RANGE = 0x80,
|
||||
NVME_SC_CAP_EXCEEDED = 0x81,
|
||||
NVME_SC_NS_NOT_READY = 0x82,
|
||||
NVME_SC_RESERVATION_CONFLICT = 0x83,
|
||||
|
||||
/*
|
||||
* Command Specific Status:
|
||||
*/
|
||||
NVME_SC_CQ_INVALID = 0x100,
|
||||
NVME_SC_QID_INVALID = 0x101,
|
||||
NVME_SC_QUEUE_SIZE = 0x102,
|
||||
NVME_SC_ABORT_LIMIT = 0x103,
|
||||
NVME_SC_ABORT_MISSING = 0x104,
|
||||
NVME_SC_ASYNC_LIMIT = 0x105,
|
||||
NVME_SC_FIRMWARE_SLOT = 0x106,
|
||||
NVME_SC_FIRMWARE_IMAGE = 0x107,
|
||||
NVME_SC_INVALID_VECTOR = 0x108,
|
||||
NVME_SC_INVALID_LOG_PAGE = 0x109,
|
||||
NVME_SC_INVALID_FORMAT = 0x10a,
|
||||
NVME_SC_FW_NEEDS_CONV_RESET = 0x10b,
|
||||
NVME_SC_INVALID_QUEUE = 0x10c,
|
||||
NVME_SC_FEATURE_NOT_SAVEABLE = 0x10d,
|
||||
NVME_SC_FEATURE_NOT_CHANGEABLE = 0x10e,
|
||||
NVME_SC_FEATURE_NOT_PER_NS = 0x10f,
|
||||
NVME_SC_FW_NEEDS_SUBSYS_RESET = 0x110,
|
||||
NVME_SC_FW_NEEDS_RESET = 0x111,
|
||||
NVME_SC_FW_NEEDS_MAX_TIME = 0x112,
|
||||
NVME_SC_FW_ACIVATE_PROHIBITED = 0x113,
|
||||
NVME_SC_OVERLAPPING_RANGE = 0x114,
|
||||
NVME_SC_NS_INSUFFICENT_CAP = 0x115,
|
||||
NVME_SC_NS_ID_UNAVAILABLE = 0x116,
|
||||
NVME_SC_NS_ALREADY_ATTACHED = 0x118,
|
||||
NVME_SC_NS_IS_PRIVATE = 0x119,
|
||||
NVME_SC_NS_NOT_ATTACHED = 0x11a,
|
||||
NVME_SC_THIN_PROV_NOT_SUPP = 0x11b,
|
||||
NVME_SC_CTRL_LIST_INVALID = 0x11c,
|
||||
NVME_SC_BP_WRITE_PROHIBITED = 0x11e,
|
||||
|
||||
/*
|
||||
* I/O Command Set Specific - NVM commands:
|
||||
*/
|
||||
NVME_SC_BAD_ATTRIBUTES = 0x180,
|
||||
NVME_SC_INVALID_PI = 0x181,
|
||||
NVME_SC_READ_ONLY = 0x182,
|
||||
NVME_SC_ONCS_NOT_SUPPORTED = 0x183,
|
||||
|
||||
/*
|
||||
* I/O Command Set Specific - Fabrics commands:
|
||||
*/
|
||||
NVME_SC_CONNECT_FORMAT = 0x180,
|
||||
NVME_SC_CONNECT_CTRL_BUSY = 0x181,
|
||||
NVME_SC_CONNECT_INVALID_PARAM = 0x182,
|
||||
NVME_SC_CONNECT_RESTART_DISC = 0x183,
|
||||
NVME_SC_CONNECT_INVALID_HOST = 0x184,
|
||||
|
||||
NVME_SC_DISCOVERY_RESTART = 0x190,
|
||||
NVME_SC_AUTH_REQUIRED = 0x191,
|
||||
|
||||
/*
|
||||
* Media and Data Integrity Errors:
|
||||
*/
|
||||
NVME_SC_WRITE_FAULT = 0x280,
|
||||
NVME_SC_READ_ERROR = 0x281,
|
||||
NVME_SC_GUARD_CHECK = 0x282,
|
||||
NVME_SC_APPTAG_CHECK = 0x283,
|
||||
NVME_SC_REFTAG_CHECK = 0x284,
|
||||
NVME_SC_COMPARE_FAILED = 0x285,
|
||||
NVME_SC_ACCESS_DENIED = 0x286,
|
||||
NVME_SC_UNWRITTEN_BLOCK = 0x287,
|
||||
|
||||
/*
|
||||
* Path-related Errors:
|
||||
*/
|
||||
NVME_SC_ANA_PERSISTENT_LOSS = 0x301,
|
||||
NVME_SC_ANA_INACCESSIBLE = 0x302,
|
||||
NVME_SC_ANA_TRANSITION = 0x303,
|
||||
|
||||
NVME_SC_DNR = 0x4000,
|
||||
};
|
||||
|
||||
const gchar *fu_nvme_status_to_string (guint32 status);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FU_NVME_COMMON_H */
|
@ -19,6 +19,7 @@
|
||||
#include <linux/nvme_ioctl.h>
|
||||
|
||||
#include "fu-chunk.h"
|
||||
#include "fu-nvme-common.h"
|
||||
#include "fu-nvme-device.h"
|
||||
|
||||
#define FU_NVME_ID_CTRL_SIZE 0x1000
|
||||
@ -100,7 +101,12 @@ fu_nvme_device_get_guid_safe (const guint8 *buf, guint16 addr_start)
|
||||
static gboolean
|
||||
fu_nvme_device_submit_admin_passthru (FuNvmeDevice *self, struct nvme_admin_cmd *cmd, GError **error)
|
||||
{
|
||||
if (ioctl (self->fd, NVME_IOCTL_ADMIN_CMD, cmd) < 0) {
|
||||
gint rc;
|
||||
guint32 err;
|
||||
|
||||
/* submit admin command */
|
||||
rc = ioctl (self->fd, NVME_IOCTL_ADMIN_CMD, cmd);
|
||||
if (rc < 0) {
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
@ -109,7 +115,26 @@ fu_nvme_device_submit_admin_passthru (FuNvmeDevice *self, struct nvme_admin_cmd
|
||||
strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
/* check the error code */
|
||||
err = rc & 0x3ff;
|
||||
switch (err) {
|
||||
case NVME_SC_SUCCESS:
|
||||
/* devices are always added with _NEEDS_REBOOT, so ignore */
|
||||
case NVME_SC_FW_NEEDS_CONV_RESET:
|
||||
case NVME_SC_FW_NEEDS_SUBSYS_RESET:
|
||||
case NVME_SC_FW_NEEDS_RESET:
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
"Not supported: %s",
|
||||
fu_nvme_status_to_string (err));
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -3,6 +3,7 @@ cargs = ['-DG_LOG_DOMAIN="FuPluginNvme"']
|
||||
shared_module('fu_plugin_nvme',
|
||||
sources : [
|
||||
'fu-plugin-nvme.c',
|
||||
'fu-nvme-common.c',
|
||||
'fu-nvme-device.c',
|
||||
],
|
||||
include_directories : [
|
||||
@ -32,6 +33,7 @@ if get_option('tests')
|
||||
'nvme-self-test',
|
||||
sources : [
|
||||
'fu-self-test.c',
|
||||
'fu-nvme-common.c',
|
||||
'fu-nvme-device.c',
|
||||
],
|
||||
include_directories : [
|
||||
|
Loading…
Reference in New Issue
Block a user