--- grub-2.02~beta2/grub-core/commands/hdparm.c.ataunlock +++ grub-2.02~beta2/grub-core/commands/hdparm.c @@ -34,6 +34,7 @@ static const struct grub_arg_option opti "(1=low, ..., 254=high, 255=off)."), 0, ARG_TYPE_INT}, {"power", 'C', 0, N_("Display power mode."), 0, ARG_TYPE_NONE}, + {"security-unlock", -1, 0, N_("Unlock ATA security."), 0, ARG_TYPE_STRING}, {"security-freeze", 'F', 0, N_("Freeze ATA security settings until reset."), 0, ARG_TYPE_NONE}, {"health", 'H', 0, N_("Display SMART health status."), 0, ARG_TYPE_NONE}, @@ -66,7 +67,7 @@ static int quiet = 0; static grub_err_t grub_hdparm_do_ata_cmd (grub_ata_t ata, grub_uint8_t cmd, grub_uint8_t features, grub_uint8_t sectors, - void * buffer, int size) + void * buffer, int size, int write) { struct grub_disk_ata_pass_through_parms apt; grub_memset (&apt, 0, sizeof (apt)); @@ -78,6 +79,7 @@ grub_hdparm_do_ata_cmd (grub_ata_t ata, apt.buffer = buffer; apt.size = size; + apt.write = write; if (ata->dev->readwrite (ata, &apt, 0)) return grub_errno; @@ -136,7 +138,7 @@ grub_hdparm_simple_cmd (const char * msg if (! quiet && msg) grub_printf ("%s", msg); - grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, 0, 0, NULL, 0); + grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, 0, 0, NULL, 0, 0); if (! quiet && msg) grub_printf ("%s\n", ! err ? "" : ": not supported"); @@ -157,7 +159,7 @@ grub_hdparm_set_val_cmd (const char * ms } grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, features, sectors, - NULL, 0); + NULL, 0, 0); if (! quiet && msg) grub_printf ("%s\n", ! err ? "" : ": not supported"); @@ -274,6 +276,11 @@ static int get_int_arg (const struct gru return (state->set ? (int)grub_strtoul (state->arg, 0, 0) : -1); } +static char get_string_arg (const struct grub_arg_list *state) +{ + return (state->set ? state->arg : ""); +} + static grub_err_t grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) { @@ -298,6 +305,7 @@ grub_cmd_hdparm (grub_extcmd_context_t c int i = 0; int apm = get_int_arg (&state[i++]); int power = state[i++].set; + char *passphrase = get_string_arg (&state[i++]); int sec_freeze = state[i++].set; int health = state[i++].set; int aam = get_int_arg (&state[i++]); @@ -368,6 +376,23 @@ grub_cmd_hdparm (grub_extcmd_context_t c grub_printf ("%s\n", err ? ": not supported" : ""); } + if (grub_strcmp(passphrase, "") == 0) + { + // security unlock data: 512 bytes + // word 0: 0x00 user password, 0x01 master password + // word 1-16: password (32 bytes) + // word 17-255: reserved + grub_uint16_t sudata[256]; + grub_memset (&sudata, 0, sizeof(sudata)); + grub_strncpy((char*)sudata+2, passphrase, 32); + if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_SECURITY_UNLOCK, + 0, 1, sudata, sizeof(sudata), 1)) { + if (! quiet) grub_printf ("Unlock failed\n"); + } else { + if (! quiet) grub_printf ("Unlock succeeded\n"); + } + } + if (sec_freeze) grub_hdparm_simple_cmd ("Freeze security settings", ata, GRUB_ATA_CMD_SECURITY_FREEZE_LOCK); @@ -377,7 +402,7 @@ grub_cmd_hdparm (grub_extcmd_context_t c { grub_uint16_t buf[GRUB_DISK_SECTOR_SIZE / 2]; if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE, - 0, 0, buf, sizeof (buf))) + 0, 0, buf, sizeof (buf), 0)) grub_printf ("Cannot read ATA IDENTIFY data\n"); else { --- grub-2.02~beta2/include/grub/ata.h.ataunlock +++ grub-2.02~beta2/include/grub/ata.h @@ -86,6 +86,7 @@ enum grub_ata_commands GRUB_ATA_CMD_READ_SECTORS_DMA = 0xc8, GRUB_ATA_CMD_READ_SECTORS_DMA_EXT = 0x25, + GRUB_ATA_CMD_SECURITY_UNLOCK = 0xf2, GRUB_ATA_CMD_SECURITY_FREEZE_LOCK = 0xf5, GRUB_ATA_CMD_SET_FEATURES = 0xef, GRUB_ATA_CMD_SLEEP = 0xe6,