Re: [PATCH 1/3] hw/ufs: Initial commit for emulated Universal-Flash-Storage
Hi Philippe, >Hi Jeuk, > >[+Alistair] > >On 26/5/23 07:05, Jeuk Kim wrote: >> Universal Flash Storage (UFS) is a high-performance mass storage device >> with a serial interface. It is primarily used as a high-performance >> data storage device for embedded applications. >> >> This commit contains code for UFS device to be recognized >> as a UFS PCI device. >> Patches to handle UFS logical unit and Transfer Request will follow. >> >> Signed-off-by: Jeuk Kim >> --- >> MAINTAINERS |6 + >> hw/Kconfig |1 + >> hw/meson.build |1 + >> hw/ufs/Kconfig |4 + >> hw/ufs/meson.build |1 + >> hw/ufs/trace-events | 33 + >> hw/ufs/trace.h |1 + >> hw/ufs/ufs.c | 305 ++ >> hw/ufs/ufs.h | 42 ++ >> include/block/ufs.h | 1251 ++ >> include/hw/pci/pci.h |1 + >> include/hw/pci/pci_ids.h |1 + >> meson.build |1 + >> 13 files changed, 1648 insertions(+) >> create mode 100644 hw/ufs/Kconfig >> create mode 100644 hw/ufs/meson.build >> create mode 100644 hw/ufs/trace-events >> create mode 100644 hw/ufs/trace.h >> create mode 100644 hw/ufs/ufs.c >> create mode 100644 hw/ufs/ufs.h >> create mode 100644 include/block/ufs.h > > >> diff --git a/include/block/ufs.h b/include/block/ufs.h >> new file mode 100644 >> index 00..0ce3a19bc0 >> --- /dev/null >> +++ b/include/block/ufs.h >> @@ -0,0 +1,1251 @@ >> +#ifndef BLOCK_UFS_H >> +#define BLOCK_UFS_H >> + >> +#include "hw/registerfields.h" > >Since you use the registerfields API, ... > >> +typedef struct QEMU_PACKED UfsReg { >> +uint32_t cap; >> +uint32_t rsvd0; >> +uint32_t ver; >> +uint32_t rsvd1; >> +uint32_t hcpid; >> +uint32_t hcmid; >> +uint32_t ahit; >> +uint32_t rsvd2; >> +uint32_t is; >> +uint32_t ie; >> +uint32_t rsvd3[2]; >> +uint32_t hcs; >> +uint32_t hce; >> +uint32_t uecpa; >> +uint32_t uecdl; >> +uint32_t uecn; >> +uint32_t uect; >> +uint32_t uecdme; >> +uint32_t utriacr; >> +uint32_t utrlba; >> +uint32_t utrlbau; >> +uint32_t utrldbr; >> +uint32_t utrlclr; >> +uint32_t utrlrsr; >> +uint32_t utrlcnr; >> +uint32_t rsvd4[2]; >> +uint32_t utmrlba; >> +uint32_t utmrlbau; >> +uint32_t utmrldbr; >> +uint32_t utmrlclr; >> +uint32_t utmrlrsr; >> +uint32_t rsvd5[3]; >> +uint32_t uiccmd; >> +uint32_t ucmdarg1; >> +uint32_t ucmdarg2; >> +uint32_t ucmdarg3; >> +uint32_t rsvd6[4]; >> +uint32_t rsvd7[4]; >> +uint32_t rsvd8[16]; >> +uint32_t ccap; >> +} UfsReg; >> + >> +enum UfsRegOfs { >> +UFS_REG_CAP = offsetof(UfsReg, cap), >> +UFS_REG_VER = offsetof(UfsReg, ver), >> +UFS_REG_HCPID = offsetof(UfsReg, hcpid), >> +UFS_REG_HCMID = offsetof(UfsReg, hcmid), >> +UFS_REG_AHIT = offsetof(UfsReg, ahit), >> +UFS_REG_IS = offsetof(UfsReg, is), >> +UFS_REG_IE = offsetof(UfsReg, ie), >> +UFS_REG_HCS = offsetof(UfsReg, hcs), >> +UFS_REG_HCE = offsetof(UfsReg, hce), >> +UFS_REG_UECPA = offsetof(UfsReg, uecpa), >> +UFS_REG_UECDL = offsetof(UfsReg, uecdl), >> +UFS_REG_UECN = offsetof(UfsReg, uecn), >> +UFS_REG_UECT = offsetof(UfsReg, uect), >> +UFS_REG_UECDME = offsetof(UfsReg, uecdme), >> +UFS_REG_UTRIACR = offsetof(UfsReg, utriacr), >> +UFS_REG_UTRLBA = offsetof(UfsReg, utrlba), >> +UFS_REG_UTRLBAU = offsetof(UfsReg, utrlbau), >> +UFS_REG_UTRLDBR = offsetof(UfsReg, utrldbr), >> +UFS_REG_UTRLCLR = offsetof(UfsReg, utrlclr), >> +UFS_REG_UTRLRSR = offsetof(UfsReg, utrlrsr), >> +UFS_REG_UTRLCNR = offsetof(UfsReg, utrlcnr), >> +UFS_REG_UTMRLBA = offsetof(UfsReg, utmrlba), >> +UFS_REG_UTMRLBAU = offsetof(UfsReg, utmrlbau), >> +UFS_REG_UTMRLDBR = offsetof(UfsReg, utmrldbr), >> +UFS_REG_UTMRLCLR = offsetof(UfsReg, utmrlclr), >> +UFS_REG_UTMRLRSR = offsetof(UfsReg, utmrlrsr), >> +UFS_REG_UICCMD = offsetof(UfsReg, uiccmd), >> +UFS_REG_UCMDARG1 = offsetof(UfsReg, ucmdarg1), >> +UFS_REG_UCMDARG2 = offsetof(UfsReg, ucmdarg2), >> +UFS_REG_UCMDARG3 = offsetof(UfsReg, ucmdarg3), >> +UFS_REG_CCAP = offsetof(UfsReg, ccap), >> +}; >> + >> +enum UfsCapShift { >> +CAP_NUTRS_SHIFT = 0, >> +CAP_RTT_SHIFT = 8, >> +CAP_NUTMRS_SHIFT = 16, >> +CAP_AUTOH8_SHIFT = 23, >> +CAP_64AS_SHIFT = 24, >> +CAP_OODDS_SHIFT = 25, >> +CAP_UICDMETMS_SHIFT = 26, >> +CAP_CS_SHIFT = 28, >> +}; >> + >> +enum UfsCapMask { >> +CAP_NUTRS_MASK = 0x1f, >> +CAP_RTT_MASK = 0xff, >> +CAP_NUTMRS_MASK = 0x7, >> +CAP_AUTOH8_MASK = 0x1, >> +CAP_64AS_MASK = 0x1, >> +CAP_OODDS_MASK = 0x1, >> +CAP_UICDMETMS_MASK = 0x1, >> +CAP_CS_MASK = 0x1, >> +}; >> + >> +#define UFS_CAP_NUTRS(cap) (((cap) >> CAP_NUTRS_SHIFT) & CAP_NUTRS_MASK) >> +#define UFS_CAP_RTT(cap) (((cap) >> CAP_RTT_SHI
Re: [PATCH 1/3] hw/ufs: Initial commit for emulated Universal-Flash-Storage
Hi Jeuk, [+Alistair] On 26/5/23 07:05, Jeuk Kim wrote: Universal Flash Storage (UFS) is a high-performance mass storage device with a serial interface. It is primarily used as a high-performance data storage device for embedded applications. This commit contains code for UFS device to be recognized as a UFS PCI device. Patches to handle UFS logical unit and Transfer Request will follow. Signed-off-by: Jeuk Kim --- MAINTAINERS |6 + hw/Kconfig |1 + hw/meson.build |1 + hw/ufs/Kconfig |4 + hw/ufs/meson.build |1 + hw/ufs/trace-events | 33 + hw/ufs/trace.h |1 + hw/ufs/ufs.c | 305 ++ hw/ufs/ufs.h | 42 ++ include/block/ufs.h | 1251 ++ include/hw/pci/pci.h |1 + include/hw/pci/pci_ids.h |1 + meson.build |1 + 13 files changed, 1648 insertions(+) create mode 100644 hw/ufs/Kconfig create mode 100644 hw/ufs/meson.build create mode 100644 hw/ufs/trace-events create mode 100644 hw/ufs/trace.h create mode 100644 hw/ufs/ufs.c create mode 100644 hw/ufs/ufs.h create mode 100644 include/block/ufs.h diff --git a/include/block/ufs.h b/include/block/ufs.h new file mode 100644 index 00..0ce3a19bc0 --- /dev/null +++ b/include/block/ufs.h @@ -0,0 +1,1251 @@ +#ifndef BLOCK_UFS_H +#define BLOCK_UFS_H + +#include "hw/registerfields.h" Since you use the registerfields API, ... +typedef struct QEMU_PACKED UfsReg { +uint32_t cap; +uint32_t rsvd0; +uint32_t ver; +uint32_t rsvd1; +uint32_t hcpid; +uint32_t hcmid; +uint32_t ahit; +uint32_t rsvd2; +uint32_t is; +uint32_t ie; +uint32_t rsvd3[2]; +uint32_t hcs; +uint32_t hce; +uint32_t uecpa; +uint32_t uecdl; +uint32_t uecn; +uint32_t uect; +uint32_t uecdme; +uint32_t utriacr; +uint32_t utrlba; +uint32_t utrlbau; +uint32_t utrldbr; +uint32_t utrlclr; +uint32_t utrlrsr; +uint32_t utrlcnr; +uint32_t rsvd4[2]; +uint32_t utmrlba; +uint32_t utmrlbau; +uint32_t utmrldbr; +uint32_t utmrlclr; +uint32_t utmrlrsr; +uint32_t rsvd5[3]; +uint32_t uiccmd; +uint32_t ucmdarg1; +uint32_t ucmdarg2; +uint32_t ucmdarg3; +uint32_t rsvd6[4]; +uint32_t rsvd7[4]; +uint32_t rsvd8[16]; +uint32_t ccap; +} UfsReg; + +enum UfsRegOfs { +UFS_REG_CAP = offsetof(UfsReg, cap), +UFS_REG_VER = offsetof(UfsReg, ver), +UFS_REG_HCPID = offsetof(UfsReg, hcpid), +UFS_REG_HCMID = offsetof(UfsReg, hcmid), +UFS_REG_AHIT = offsetof(UfsReg, ahit), +UFS_REG_IS = offsetof(UfsReg, is), +UFS_REG_IE = offsetof(UfsReg, ie), +UFS_REG_HCS = offsetof(UfsReg, hcs), +UFS_REG_HCE = offsetof(UfsReg, hce), +UFS_REG_UECPA = offsetof(UfsReg, uecpa), +UFS_REG_UECDL = offsetof(UfsReg, uecdl), +UFS_REG_UECN = offsetof(UfsReg, uecn), +UFS_REG_UECT = offsetof(UfsReg, uect), +UFS_REG_UECDME = offsetof(UfsReg, uecdme), +UFS_REG_UTRIACR = offsetof(UfsReg, utriacr), +UFS_REG_UTRLBA = offsetof(UfsReg, utrlba), +UFS_REG_UTRLBAU = offsetof(UfsReg, utrlbau), +UFS_REG_UTRLDBR = offsetof(UfsReg, utrldbr), +UFS_REG_UTRLCLR = offsetof(UfsReg, utrlclr), +UFS_REG_UTRLRSR = offsetof(UfsReg, utrlrsr), +UFS_REG_UTRLCNR = offsetof(UfsReg, utrlcnr), +UFS_REG_UTMRLBA = offsetof(UfsReg, utmrlba), +UFS_REG_UTMRLBAU = offsetof(UfsReg, utmrlbau), +UFS_REG_UTMRLDBR = offsetof(UfsReg, utmrldbr), +UFS_REG_UTMRLCLR = offsetof(UfsReg, utmrlclr), +UFS_REG_UTMRLRSR = offsetof(UfsReg, utmrlrsr), +UFS_REG_UICCMD = offsetof(UfsReg, uiccmd), +UFS_REG_UCMDARG1 = offsetof(UfsReg, ucmdarg1), +UFS_REG_UCMDARG2 = offsetof(UfsReg, ucmdarg2), +UFS_REG_UCMDARG3 = offsetof(UfsReg, ucmdarg3), +UFS_REG_CCAP = offsetof(UfsReg, ccap), +}; + +enum UfsCapShift { +CAP_NUTRS_SHIFT = 0, +CAP_RTT_SHIFT = 8, +CAP_NUTMRS_SHIFT = 16, +CAP_AUTOH8_SHIFT = 23, +CAP_64AS_SHIFT = 24, +CAP_OODDS_SHIFT = 25, +CAP_UICDMETMS_SHIFT = 26, +CAP_CS_SHIFT = 28, +}; + +enum UfsCapMask { +CAP_NUTRS_MASK = 0x1f, +CAP_RTT_MASK = 0xff, +CAP_NUTMRS_MASK = 0x7, +CAP_AUTOH8_MASK = 0x1, +CAP_64AS_MASK = 0x1, +CAP_OODDS_MASK = 0x1, +CAP_UICDMETMS_MASK = 0x1, +CAP_CS_MASK = 0x1, +}; + +#define UFS_CAP_NUTRS(cap) (((cap) >> CAP_NUTRS_SHIFT) & CAP_NUTRS_MASK) +#define UFS_CAP_RTT(cap) (((cap) >> CAP_RTT_SHIFT) & CAP_RTT_MASK) +#define UFS_CAP_NUTMRS(cap) (((cap) >> CAP_NUTMRS_SHIFT) & CAP_NUTMRS_MASK) +#define UFS_CAP_AUTOH8(cap) (((cap) >> CAP_AUTOH8_SHIFT) & CAP_AUTOH8_MASK) +#define UFS_CAP_64AS(cap) (((cap) >> CAP_64AS_SHIFT) & CAP_64AS_MASK) +#define UFS_CAP_OODDS(cap) (((cap) >> CAP_OODDS_SHIFT) & CAP_OODDS_MASK) +#define UFS_CAP_UICDMETMS(cap) \ +(((cap) >> CAP_UICDMETMS_SHIFT) & CAP_UICDMETMS_MASK) +#define UFS_CAP_CS(cap) (((cap)
Re: [PATCH 1/3] hw/ufs: Initial commit for emulated Universal-Flash-Storage
On 30/05/2023 03.36, Jeuk Kim wrote: On 26/05/2023 15:37, Thomas Huth wrote: On 26/05/2023 07.05, Jeuk Kim wrote: Universal Flash Storage (UFS) is a high-performance mass storage device with a serial interface. It is primarily used as a high-performance data storage device for embedded applications. This commit contains code for UFS device to be recognized as a UFS PCI device. Patches to handle UFS logical unit and Transfer Request will follow. Signed-off-by: Jeuk Kim --- MAINTAINERS |6 + hw/Kconfig |1 + hw/meson.build |1 + hw/ufs/Kconfig |4 + hw/ufs/meson.build |1 + hw/ufs/trace-events | 33 + hw/ufs/trace.h |1 + hw/ufs/ufs.c | 305 ++ hw/ufs/ufs.h | 42 ++ include/block/ufs.h | 1251 ++ include/hw/pci/pci.h |1 + include/hw/pci/pci_ids.h |1 + meson.build |1 + Do you expect lots of additional files to be added to the hw/ufs/ folder? If the answer is no, then it's maybe a little bit overkill to introduce a separate folder for this. Wouldn't hw/block/ be a good fit for this as well? Or maybe we could introduce hw/flash/ or so and also move the contents of hw/nvme there? Yes. I plan to add more files to UFS for different functions (UICCMD, MQ, zoned, etc.) like nvme. So personally, I think it would be good to keep the hw/ufs/ directory. Ok, fair. Then start with hw/ufs/ first and we'll see how it goes. We can still move the files later if necessary. Thomas
Re: [PATCH 1/3] hw/ufs: Initial commit for emulated Universal-Flash-Storage
On 26/05/2023 15:37, Thomas Huth wrote: >On 26/05/2023 07.05, Jeuk Kim wrote: >> Universal Flash Storage (UFS) is a high-performance mass storage device >> with a serial interface. It is primarily used as a high-performance >> data storage device for embedded applications. >> >> This commit contains code for UFS device to be recognized >> as a UFS PCI device. >> Patches to handle UFS logical unit and Transfer Request will follow. >> >> Signed-off-by: Jeuk Kim >> --- >> MAINTAINERS |6 + >> hw/Kconfig |1 + >> hw/meson.build |1 + >> hw/ufs/Kconfig |4 + >> hw/ufs/meson.build |1 + >> hw/ufs/trace-events | 33 + >> hw/ufs/trace.h |1 + >> hw/ufs/ufs.c | 305 ++ >> hw/ufs/ufs.h | 42 ++ >> include/block/ufs.h | 1251 ++ >> include/hw/pci/pci.h |1 + >> include/hw/pci/pci_ids.h |1 + >> meson.build |1 + > >Do you expect lots of additional files to be added to the hw/ufs/ folder? If >the answer is no, then it's maybe a little bit overkill to introduce a >separate folder for this. Wouldn't hw/block/ be a good fit for this as well? >Or maybe we could introduce hw/flash/ or so and also move the contents of >hw/nvme there? Yes. I plan to add more files to UFS for different functions (UICCMD, MQ, zoned, etc.) like nvme. So personally, I think it would be good to keep the hw/ufs/ directory.
Re: [PATCH 1/3] hw/ufs: Initial commit for emulated Universal-Flash-Storage
On 26/05/2023 07.05, Jeuk Kim wrote: Universal Flash Storage (UFS) is a high-performance mass storage device with a serial interface. It is primarily used as a high-performance data storage device for embedded applications. This commit contains code for UFS device to be recognized as a UFS PCI device. Patches to handle UFS logical unit and Transfer Request will follow. Signed-off-by: Jeuk Kim --- MAINTAINERS |6 + hw/Kconfig |1 + hw/meson.build |1 + hw/ufs/Kconfig |4 + hw/ufs/meson.build |1 + hw/ufs/trace-events | 33 + hw/ufs/trace.h |1 + hw/ufs/ufs.c | 305 ++ hw/ufs/ufs.h | 42 ++ include/block/ufs.h | 1251 ++ include/hw/pci/pci.h |1 + include/hw/pci/pci_ids.h |1 + meson.build |1 + Do you expect lots of additional files to be added to the hw/ufs/ folder? If the answer is no, then it's maybe a little bit overkill to introduce a separate folder for this. Wouldn't hw/block/ be a good fit for this as well? Or maybe we could introduce hw/flash/ or so and also move the contents of hw/nvme there? Thomas
[PATCH 1/3] hw/ufs: Initial commit for emulated Universal-Flash-Storage
Universal Flash Storage (UFS) is a high-performance mass storage device with a serial interface. It is primarily used as a high-performance data storage device for embedded applications. This commit contains code for UFS device to be recognized as a UFS PCI device. Patches to handle UFS logical unit and Transfer Request will follow. Signed-off-by: Jeuk Kim --- MAINTAINERS |6 + hw/Kconfig |1 + hw/meson.build |1 + hw/ufs/Kconfig |4 + hw/ufs/meson.build |1 + hw/ufs/trace-events | 33 + hw/ufs/trace.h |1 + hw/ufs/ufs.c | 305 ++ hw/ufs/ufs.h | 42 ++ include/block/ufs.h | 1251 ++ include/hw/pci/pci.h |1 + include/hw/pci/pci_ids.h |1 + meson.build |1 + 13 files changed, 1648 insertions(+) create mode 100644 hw/ufs/Kconfig create mode 100644 hw/ufs/meson.build create mode 100644 hw/ufs/trace-events create mode 100644 hw/ufs/trace.h create mode 100644 hw/ufs/ufs.c create mode 100644 hw/ufs/ufs.h create mode 100644 include/block/ufs.h diff --git a/MAINTAINERS b/MAINTAINERS index 1c93ab0ee5..b80ba5e431 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2229,6 +2229,12 @@ F: tests/qtest/nvme-test.c F: docs/system/devices/nvme.rst T: git git://git.infradead.org/qemu-nvme.git nvme-next +ufs +M: Jeuk Kim +S: Supported +F: hw/ufs/* +F: include/block/ufs.h + megasas M: Hannes Reinecke L: qemu-bl...@nongnu.org diff --git a/hw/Kconfig b/hw/Kconfig index ba62ff6417..9ca7b38c31 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -38,6 +38,7 @@ source smbios/Kconfig source ssi/Kconfig source timer/Kconfig source tpm/Kconfig +source ufs/Kconfig source usb/Kconfig source virtio/Kconfig source vfio/Kconfig diff --git a/hw/meson.build b/hw/meson.build index c7ac7d3d75..f01fac4617 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -37,6 +37,7 @@ subdir('smbios') subdir('ssi') subdir('timer') subdir('tpm') +subdir('ufs') subdir('usb') subdir('vfio') subdir('virtio') diff --git a/hw/ufs/Kconfig b/hw/ufs/Kconfig new file mode 100644 index 00..b7b3392e85 --- /dev/null +++ b/hw/ufs/Kconfig @@ -0,0 +1,4 @@ +config UFS_PCI +bool +default y if PCI_DEVICES +depends on PCI diff --git a/hw/ufs/meson.build b/hw/ufs/meson.build new file mode 100644 index 00..c1d90eeea6 --- /dev/null +++ b/hw/ufs/meson.build @@ -0,0 +1 @@ +softmmu_ss.add(when: 'CONFIG_UFS_PCI', if_true: files('ufs.c')) diff --git a/hw/ufs/trace-events b/hw/ufs/trace-events new file mode 100644 index 00..17793929b1 --- /dev/null +++ b/hw/ufs/trace-events @@ -0,0 +1,33 @@ +# ufs.c +ufs_irq_raise(void) "INTx" +ufs_irq_lower(void) "INTx" +ufs_mmio_read(uint64_t addr, uint64_t data, unsigned size) "addr 0x%"PRIx64" data 0x%"PRIx64" size %d" +ufs_mmio_write(uint64_t addr, uint64_t data, unsigned size) "addr 0x%"PRIx64" data 0x%"PRIx64" size %d" +ufs_process_db(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_process_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_complete_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_sendback_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_exec_nop_cmd(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_exec_scsi_cmd(uint32_t slot, uint8_t lun, uint8_t opcode) "slot %"PRIu32", lun 0x%"PRIx8", opcode 0x%"PRIx8"" +ufs_exec_query_cmd(uint32_t slot, uint8_t opcode) "slot %"PRIu32", opcode 0x%"PRIx8"" +ufs_process_uiccmd(uint32_t uiccmd, uint32_t ucmdarg1, uint32_t ucmdarg2, uint32_t ucmdarg3) "uiccmd 0x%"PRIx32", ucmdarg1 0x%"PRIx32", ucmdarg2 0x%"PRIx32", ucmdarg3 0x%"PRIx32"" + +# error condition +ufs_err_memory_allocation(void) "failed to allocate memory" +ufs_err_dma_read_utrd(uint32_t slot, uint64_t addr) "failed to read utrd. UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64"" +ufs_err_dma_read_req_upiu(uint32_t slot, uint64_t addr) "failed to read req upiu. UTRLDBR slot %"PRIu32", request upiu addr %"PRIu64"" +ufs_err_dma_read_prdt(uint32_t slot, uint64_t addr) "failed to read prdt. UTRLDBR slot %"PRIu32", prdt addr %"PRIu64"" +ufs_err_dma_write_utrd(uint32_t slot, uint64_t addr) "failed to write utrd. UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64"" +ufs_err_dma_write_rsp_upiu(uint32_t slot, uint64_t addr) "failed to write rsp upiu. UTRLDBR slot %"PRIu32", response upiu addr %"PRIu64"" +ufs_err_utrl_slot_busy(uint32_t slot) "UTRLDBR slot %"PRIu32" is busy" +ufs_err_unsupport_register_offset(uint32_t offset) "Register offset 0x%"PRIx32" is not yet supported" +ufs_err_invalid_register_offset(uint32_t offset) "Register offset 0x%"PRIx32" is invalid" +ufs_err_scsi_cmd_invalid_lun(uint8_t lun) "scsi command has invalid lun: 0x%"PRIx8"" +ufs_err_query_flag_not_readable(uint8_t idn) "query flag idn 0x%"PRIx8" is denied to read" +ufs_err_query_flag_not_writable(uint8_t idn) "query flag idn 0x%"PRIx8" is denied to write" +ufs_err_query_attr_not_readable(uint8_t idn) "query attribute idn