Hi all,
here's a patch for unlocking the ATA password from grub command line. As
mentioned in [1] it does not prompt for a password at boot but enables
the hdparm module to support the security unlock feature.
In case anyone asks, the patch is GPL.
Kind regards
Philippe
[1] https://www.unixadm.org/needful-things/ataunlock#using-grub2
--- 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,
_______________________________________________
Grub-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel