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
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to