ufs-utils ffu [-t] <ffu cmd idn> [-p] <path to device>?
-t FFU cmd idn 0 : FFU, flash FFU 1 : Check FFU status (check FFU status attribute and display FW version)
-s Max chunk size in KB alignment to 4KB, which FFU file will be split (optional)
-w path to FFU file
-g sg struct ver - 0: SG_IO_VER4 (default), 1: SG_IO_VER3
-p bsg device path for FFU, ufs-bsg for Check FFU status
-p的bsg device path就是前面提到的/dev/0:0:0:0(sg v4) or /dev/block/sda(sg v3)。
usf-bsg用于Check FFU status,device是/dev/ufs-bsg。
what is ufs bsg? 看文档:
BSG Support
This transport driver supports exchanging UFS protocol information units (UPIUs) with a UFS device. Typically, user space will allocate struct ufs_bsg_request and struct ufs_bsg_reply (see ufs_bsg.h) as request_upiu and reply_upiu respectively. Filling those UPIUs should be done in accordance with JEDEC spec UFS2.1 paragraph 10.7. Caveat emptor: The driver makes no further input validations and sends the UPIU to the device as it is. Open the bsg device in /dev/ufs-bsg and send SG_IO with the applicable sg_io_v4::
config SCSI_UFS_BSG bool "Universal Flash Storage BSG device node" depends on SCSI_UFSHCD select BLK_DEV_BSGLIB help Universal Flash Storage (UFS) is SCSI transport specification for accessing flash storage on digital cameras, mobile phones and consumer electronic devices. A UFS controller communicates with a UFS device by exchanging UFS Protocol Information Units (UPIUs). UPIUs can not only be used as a transport layer for the SCSI protocol but are also used by the UFS native command set. This transport driver supports exchanging UFS protocol information units with a UFS device. See also the ufshcd driver, which is a SCSI driver that supports UFS devices.
Select this if you need a bsg device node for your UFS controller. If unsure, say N.
重点是UPIUs are also used by the UFS native command set。
ufshcd-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o
code是driver\scsi\ufs\ufs_bsg.c。
/* * bsg endpoint that supports UPIUs * * Copyright (C) 2018 Western Digital Corporation */ #include"ufs_bsg.h"
What: /sys/bus/platform/drivers/ufshcd/*/attributes/ffu_status Date: February 2018 Contact: Stanislav Nijnikov stanislav.nijnikov@wdc.com Description: This file provides the ffu status UFS device attribute. The full information about the attribute could be found at UFS specifications 2.1. The file is read only.
ufs spec的定义:
The column “MDV” (Manufacturer Default Value) specifies atrribute values after device manufacturing
Err: Command fail with status 1 , senseKey Miscompare
Err: SG_IO WRITE BUFFER data error ret -22
Err: Write error -22:
工具默认没开debug,打开即可:
-#CXXFLAGS = -DDEBUG +CXXFLAGS = -DDEBUG
senseKey Miscompare是啥意思?我们先看工具code:
/* description of the sense key values */ staticconstchar *const snstext[] = { "No Sense", /* 0: There is no sense information */ "Recovered Error", /* 1: The last command completed successfully but used error correction */ "Not Ready", /* 2: The addressed target is not ready */ "Medium Error", /* 3: Data error detected on the medium */ "Hardware Error", /* 4: Controller or device failure */ "Illegal Request", /* 5: Error in request */ "Unit Attention", /* 6: Removable medium was changed, or the target has been reset, or ... */ "Data Protect", /* 7: Access to the data is blocked */ "Blank Check", /* 8: Reached unexpected written or unwritten region of the medium */ "Vendor Specific", "Copy Aborted", /* A: COPY or COMPARE was aborted */ "Aborted Command", /* B: The target aborted the command */ "Equal", /* C: A SEARCH DATA command found data equal */ "Volume Overflow", /* D: Medium full with still data to be written */ "Miscompare", /* E: Source data and data on the medium do not agree */
/** * send_scsi_cmd - Utility function for SCSI command sending * @fd: bsg driver file descriptor * @cdb: pointer to SCSI cmd cdb buffer * @buf: pointer to the SCSI cmd data buffer * @cmd_len: SCSI command length * @byte_cnt: SCSI data length * @dir: The cmd direction * **/ staticintsend_scsi_cmd(int fd, const __u8 *cdb, void *buf, __u8 cmd_len, __u32 byte_cnt, int dir, __u8 sg_type) { ... else { io_hdr_v3.interface_id = 'S'; io_hdr_v3.cmd_len = cmd_len; io_hdr_v3.mx_sb_len = SENSE_BUFF_LEN; io_hdr_v3.dxfer_direction = dir; io_hdr_v3.dxfer_len = byte_cnt; io_hdr_v3.dxferp = buf; /* pointer to command buf (rbufCmdBlk) */ io_hdr_v3.cmdp = (unsignedchar *)cdb; io_hdr_v3.sbp = sense_buffer; //tj: here io_hdr_v3.timeout = DEF_TIMEOUT_MSEC; sg_struct = &io_hdr_v3; } WRITE_LOG("Start : %s cmd = %x len %d sg_type %d\n", __func__, cdb[0], byte_cnt, sg_type);
while (((ret = ioctl(fd, SG_IO, sg_struct)) < 0) && ((errno == EINTR) || (errno == EAGAIN))); if (sg_type == SG4_TYPE) { if (io_hdr_v4.info != 0) { print_error("Command fail with status %x , senseKey %s", io_hdr_v4.info, sense_key_string(sense_buffer[2])); ret = -EINVAL; } } else { if (io_hdr_v3.status) { print_error("Command fail with status %x , senseKey %s", io_hdr_v3.status, sense_key_string(sense_buffer[2])); ret = -EINVAL; }
}
用的是v3,io_hdr_v3.status是1,ioctl cmd是SG_IO。
看下v3 interface:
/* * SCSI Generic v3 struct copied from include/scsi/sg.h */ typedefstructsg_io_hdr { int interface_id; /* [i] 'S' for SCSI generic (required) */ int dxfer_direction; /* [i] data transfer direction */ unsignedchar cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ unsignedchar mx_sb_len; /* [i] max length to write to sbp */ unsignedshortint iovec_count; /* [i] 0 implies no scatter gather */ unsignedint dxfer_len; /* [i] byte count of data transfer */ void *dxferp; /* [i], [*io] points to data transfer memory or scatter gather list */ unsignedchar *cmdp; /* [i], [*i] points to command to perform */ unsignedchar *sbp; /* [i], [*o] points to sense_buffer memory *///tj:here