]> git.proxmox.com Git - grub2.git/commitdiff
ARC disk write support.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 25 Jan 2012 15:13:34 +0000 (16:13 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 25 Jan 2012 15:13:34 +0000 (16:13 +0100)
* grub-core/disk/arc/arcdisk.c (handle_writable): New var.
(reopen): New argument writable. All users updated.
Handle required access mode.
(grub_arcdisk_write): Implement.
* include/grub/arc/arc.h (grub_arc_file_access): New enum.
(grub_arc_firmware_vector): Make buffer to write a const buffer.

ChangeLog
grub-core/disk/arc/arcdisk.c
include/grub/arc/arc.h

index f4b5606fe2c36902814d66710cb4eb660c54571e..b1f6647317a549f9453d11ef27a3fad2d9b0313d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-01-25  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       ARC disk write support.
+
+       * grub-core/disk/arc/arcdisk.c (handle_writable): New var.
+       (reopen): New argument writable. All users updated.
+       Handle required access mode.
+       (grub_arcdisk_write): Implement.
+       * include/grub/arc/arc.h (grub_arc_file_access): New enum.
+       (grub_arc_firmware_vector): Make buffer to write a const buffer.
+
 2012-01-25  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/fs/btrfs.c (grub_btrfs_device): New field size.
index 170bf521dff9dd044edb861f48919dee0965190e..198dfcfff0a6e01588ef80733ce0960e23272666 100644 (file)
@@ -24,6 +24,7 @@
 
 static grub_arc_fileno_t last_handle = 0;
 static char *last_path = NULL;
+static int handle_writable = 0;
 
 static int lnum = 0;
 
@@ -100,11 +101,12 @@ grub_arcdisk_iterate (int (*hook_in) (const char *name),
 #define RAW_SUFFIX "partition(10)"
 
 static grub_err_t
-reopen (const char *name)
+reopen (const char *name, int writable)
 {
   grub_arc_fileno_t handle;
 
-  if (last_path && grub_strcmp (last_path, name) == 0)
+  if (last_path && grub_strcmp (last_path, name) == 0
+      && (!writable || handle_writable))
     {
       grub_dprintf ("arcdisk", "using already opened %s\n", name);
       return GRUB_ERR_NONE;
@@ -115,12 +117,16 @@ reopen (const char *name)
       grub_free (last_path);
       last_path = NULL;
       last_handle = 0;
+      handle_writable = 0;
     }
-  if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle))
+  if (GRUB_ARC_FIRMWARE_VECTOR->open (name,
+                                     writable ? GRUB_ARC_FILE_ACCESS_OPEN_RW
+                                     : GRUB_ARC_FILE_ACCESS_OPEN_RO, &handle))
     {
       grub_dprintf ("arcdisk", "couldn't open %s\n", name);
       return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
     }
+  handle_writable = writable;
   last_path = grub_strdup (name);
   if (!last_path)
     return grub_errno;
@@ -180,7 +186,7 @@ grub_arcdisk_open (const char *name, grub_disk_t disk)
   if (!hash)
     return grub_errno;
 
-  err = reopen (fullname);
+  err = reopen (fullname, 0);
   if (err)
     return err;
 
@@ -234,7 +240,7 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
   grub_uint64_t totl = size << 9;
   grub_arc_err_t r;
 
-  err = reopen (disk->data);
+  err = reopen (disk->data, 0);
   if (err)
     return err;
   r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
@@ -258,12 +264,36 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
 }
 
 static grub_err_t
-grub_arcdisk_write (grub_disk_t disk __attribute ((unused)),
-                  grub_disk_addr_t sector __attribute ((unused)),
-                  grub_size_t size __attribute ((unused)),
-                  const char *buf __attribute ((unused)))
+grub_arcdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
+                   grub_size_t size, const char *buf)
 {
-  return GRUB_ERR_NOT_IMPLEMENTED_YET;
+  grub_err_t err;
+  grub_uint64_t pos = sector << 9;
+  unsigned long count;
+  grub_uint64_t totl = size << 9;
+  grub_arc_err_t r;
+
+  err = reopen (disk->data, 1);
+  if (err)
+    return err;
+  r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
+  if (r)
+    {
+      grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %ld\n",
+                   pos, r);
+      return grub_error (GRUB_ERR_IO, "couldn't seek");
+    }
+
+  while (totl)
+    {
+      if (GRUB_ARC_FIRMWARE_VECTOR->write (last_handle, buf,
+                                          totl, &count))
+       return grub_error (GRUB_ERR_WRITE_ERROR, "write failed");
+      totl -= count;
+      buf += count;
+    }
+
+  return GRUB_ERR_NONE;
 }
 
 static struct grub_disk_dev grub_arcdisk_dev =
index aae73052be62d607f016e79b7f1560842edd84c5..a825a98777745eca4e25a2f2f020babfb2e28e22 100644 (file)
@@ -139,6 +139,13 @@ enum
     GRUB_ARC_COMPONENT_TYPE_MEMORY_UNIT,
   };
 
+enum grub_arc_file_access
+  {
+    GRUB_ARC_FILE_ACCESS_OPEN_RO,
+    GRUB_ARC_FILE_ACCESS_OPEN_WO,
+    GRUB_ARC_FILE_ACCESS_OPEN_RW,
+  };
+
 struct grub_arc_fileinfo
 {
   grub_arc_ularge_t start;
@@ -195,7 +202,7 @@ struct grub_arc_firmware_vector
                          grub_arc_ulong_t n,
                          grub_arc_ulong_t *count);
   grub_arc_err_t (*get_read_status) (grub_arc_fileno_t fileno);
-  grub_arc_err_t (*write) (grub_arc_fileno_t fileno, void *buf,
+  grub_arc_err_t (*write) (grub_arc_fileno_t fileno, const void *buf,
                           grub_arc_ulong_t n,
                           grub_arc_ulong_t *count);