Skip to content

Commit

Permalink
Merge pull request wolfSSL#361 from danielinux/ata-disk-lock
Browse files Browse the repository at this point in the history
Support for ATA Security feature set
  • Loading branch information
rizlik authored Sep 5, 2023
2 parents d9350a6 + 87f97c1 commit 1c048a2
Show file tree
Hide file tree
Showing 5 changed files with 338 additions and 14 deletions.
38 changes: 37 additions & 1 deletion include/x86/ata.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct __attribute__((packed)) hba_cmd_header {
uint8_t r:1, b:1, c:1, _res0:1, pmp:4;
uint16_t prdtl;

uint32_t prbdc;
volatile uint32_t prbdc;

uint32_t ctba;
uint32_t ctbau;
Expand All @@ -42,6 +42,25 @@ int ata_drive_write(int drv, uint64_t start, uint32_t count,
const uint8_t *buf);
int ata_identify_device(int drv);

int ata_device_config_identify(int drv);
int ata_security_freeze_lock(int drv);
int ata_security_unlock_device(int drv, const char *passphrase);

/* @brief Enum with the possible state for each drive.
* See ATA/ATAPI Command Set (ATA8-ACS) section 4.7.4
*/
enum ata_security_state {
ATA_SEC0 = 0, /* SEC0: Powered down/Security disabled */
ATA_SEC1, /* SEC1: Security disabled/not Frozen */
ATA_SEC2, /* SEC2: Security disabled/Frozen */
_ATA_POFF3, /* SEC3: Powered down/Security enabled */
ATA_SEC4, /* SEC4: Security enabled/Locked */
ATA_SEC5, /* SEC5: Unlocked/not Frozen */
ATA_SEC6 /* SEC6: Unlocked/ Frozen */
};

enum ata_security_state ata_security_get_state(int);

#define ATA_DEV_BUSY (1 << 7)
#define ATA_DEV_DRQ (1 << 3)

Expand All @@ -59,11 +78,28 @@ int ata_identify_device(int drv);
#define FIS_LEN_H2D 20
#define FIS_H2D_CMD (1 << 7)


/* ATA commands */

#define ATA_CMD_READ_DMA_EX 0x25
#define ATA_CMD_WRITE_DMA_EX 0x35
#define ATA_CMD_DEVICE_CONFIGURATION_IDENTIFY 0xB1
#define ATA_CMD_WRITE_DMA 0xCA
#define ATA_CMD_IDENTIFY_DEVICE 0xEC

#define ATA_IDENTIFY_DEVICE_COMMAND_LEN (256 * 2)


/* Security feature set */
#define ATA_CMD_SECURITY_SET_PASSWORD 0xF1
#define ATA_CMD_SECURITY_UNLOCK 0xF2
#define ATA_CMD_SECURITY_ERASE_PREPARE 0xF3
#define ATA_CMD_SECURITY_ERASE_UNIT 0xF4
#define ATA_CMD_SECURITY_FREEZE_LOCK 0xF5
#define ATA_CMD_SECURITY_DISABLE_PASSWORD 0xF6

/* Constants for security set commands */
#define ATA_SECURITY_COMMAND_LEN (256 * 2)
#define ATA_SECURITY_PASSWORD_OFFSET (1 * 2)

#endif
5 changes: 5 additions & 0 deletions options.mk
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,11 @@ ifeq ($(64BIT),1)
CFLAGS+=-DWOLFBOOT_64BIT
endif

ifeq ($(DISK_LOCK),1)
CFLAGS+=-DWOLFBOOT_ATA_DISK_LOCK
CFLAGS+=-DWOLFBOOT_ATA_DISK_LOCK_PASSWORD=\"$(DISK_LOCK_PASSWORD)\"
endif

ifeq ($(FSP), 1)
X86_FSP_OPTIONS := \
X86_UART_BASE \
Expand Down
40 changes: 40 additions & 0 deletions src/x86/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ void sata_enable(uint32_t base) {
uint8_t ipm = (ssts >> 8) & 0xFF;
uint8_t det = ssts & 0x0F;
volatile struct hba_cmd_header *hdr;
#ifdef WOLFBOOT_ATA_DISK_LOCK
const char user_passphrase[] = WOLFBOOT_ATA_DISK_LOCK_PASSWORD;
#endif

data = mmio_read32(AHCI_PxCMD(base, i));
/* Detect POD */
Expand Down Expand Up @@ -381,10 +384,47 @@ void sata_enable(uint32_t base) {
} else {
char buf[512] ="";
int r;
enum ata_security_state ata_st;
AHCI_DEBUG_PRINTF("ATA%d associated to AHCI port %d\r\n",
drv, i);
r = ata_identify_device(drv);
AHCI_DEBUG_PRINTF("ATA identify: returned %d\r\n", r);


#ifdef WOLFBOOT_ATA_DISK_LOCK
ata_st = ata_security_get_state(drv);
wolfBoot_printf("ATA: Security state SEC%d\r\n", ata_st);
if (ata_st == ATA_SEC1) {
AHCI_DEBUG_PRINTF("ATA identify: calling freeze lock\r\n", r);
r = ata_security_freeze_lock(drv);
AHCI_DEBUG_PRINTF("ATA security freeze lock: returned %d\r\n", r);
r = ata_identify_device(drv);
AHCI_DEBUG_PRINTF("ATA identify: returned %d\r\n", r);
ata_st = ata_security_get_state(drv);
wolfBoot_printf("ATA: Security disabled. State SEC%d\r\n", ata_st);
}
else if (ata_st == ATA_SEC4) {
AHCI_DEBUG_PRINTF("ATA identify: calling device unlock\r\n", r);
r = ata_security_unlock_device(drv, user_passphrase);
AHCI_DEBUG_PRINTF("ATA device unlock: returned %d\r\n", r);
r = ata_identify_device(drv);
AHCI_DEBUG_PRINTF("ATA identify: returned %d\r\n", r);
ata_st = ata_security_get_state(drv);
if (ata_st == ATA_SEC5) {
AHCI_DEBUG_PRINTF("ATA identify: calling device freeze\r\n", r);
r = ata_security_freeze_lock(drv);
AHCI_DEBUG_PRINTF("ATA device freeze: returned %d\r\n", r);
r = ata_identify_device(drv);
AHCI_DEBUG_PRINTF("ATA identify: returned %d\r\n", r);
}
ata_st = ata_security_get_state(drv);
if (ata_st != ATA_SEC6) {
panic();
}
ata_st = ata_security_get_state(drv);
wolfBoot_printf("ATA: Security enabled. State SEC%d\r\n", ata_st);
}
#endif
}
} else {
AHCI_DEBUG_PRINTF("AHCI port %d: device with signature %08x is not supported\r\n",
Expand Down
Loading

0 comments on commit 1c048a2

Please sign in to comment.