]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Add progress module to display load progress of files.
authorPaulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Tue, 22 Oct 2013 18:42:20 +0000 (16:42 -0200)
committerPaulo Flabiano Smorigo <pfsmorigo@gmail.com>
Tue, 22 Oct 2013 18:42:20 +0000 (16:42 -0200)
* grub-core/lib/progress.c: New file.
* grub-core/Makefile.core.def (progress): New module.
* grub-core/kern/file.c (grub_file_open): File name added.
* (grub_file_read): Progress hook added.
* grub-core/fs/cbfs.c (grub_cbfs_read): Likewise.
* grub-core/fs/cpio_common.c (grub_cpio_read): Likewise.
* grub-core/net/net.c (grub_net_fs_read_real): Likewise.
* include/grub/file.h (struct grub_file): Add progress module
* members.
* include/grub/term.h (struct grub_term_output): Likewise.
* grub-core/osdep/unix/emuconsole.c (grub_console_term_output):
Terminal velocity added.
* grub-core/osdep/windows/emuconsole.c (grub_console_term_output):
* Likewise.
* grub-core/term/arc/console.c (grub_console_term_output): Likewise.
* grub-core/term/efi/console.c (grub_console_term_output): Likewise.
* grub-core/term/gfxterm.c (grub_video_term): Likewise.
* grub-core/term/i386/coreboot/cbmemc.c (grub_cbmemc_term_output):
* Likewise.
* grub-core/term/i386/pc/console.c (grub_console_term_output):
* Likewise.
* grub-core/term/i386/pc/vga_text.c (grub_vga_text_term): Likewise.
* grub-core/term/ieee1275/console.c (grub_console_term_output):
* Likewise.
* grub-core/term/morse.c (grub_audio_term_output): Likewise.
* grub-core/term/serial.c (grub_serial_term_output): Likewise.
* grub-core/term/spkmodem.c (grub_spkmodem_term_output): Likewise.
* grub-core/term/uboot/console.c (uboot_console_term_output):
* Likewise.

22 files changed:
ChangeLog
grub-core/Makefile.core.def
grub-core/fs/cbfs.c
grub-core/fs/cpio_common.c
grub-core/kern/file.c
grub-core/lib/progress.c [new file with mode: 0644]
grub-core/net/net.c
grub-core/osdep/unix/emuconsole.c
grub-core/osdep/windows/emuconsole.c
grub-core/term/arc/console.c
grub-core/term/efi/console.c
grub-core/term/gfxterm.c
grub-core/term/i386/coreboot/cbmemc.c
grub-core/term/i386/pc/console.c
grub-core/term/i386/pc/vga_text.c
grub-core/term/ieee1275/console.c
grub-core/term/morse.c
grub-core/term/serial.c
grub-core/term/spkmodem.c
grub-core/term/uboot/console.c
include/grub/file.h
include/grub/term.h

index a4a0a87ce24fbbe22fadae8b4f8d10819dc00a03..ba18817a416dc9e440b5321a416dd50366756a95 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2013-10-22  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
+
+       Add new progress module that displays the load progress of files.
+
+       * grub-core/lib/progress.c: New file.
+       * grub-core/Makefile.core.def (progress): New module.
+       * grub-core/kern/file.c (grub_file_open): File name added.
+       * (grub_file_read): Progress hook added.
+       * grub-core/fs/cbfs.c (grub_cbfs_read): Likewise.
+       * grub-core/fs/cpio_common.c (grub_cpio_read): Likewise.
+       * grub-core/net/net.c (grub_net_fs_read_real): Likewise.
+       * include/grub/file.h (struct grub_file): Add progress module members.
+       * include/grub/term.h (struct grub_term_output): Likewise.
+       * grub-core/osdep/unix/emuconsole.c (grub_console_term_output):
+       Terminal velocity added.
+       * grub-core/osdep/windows/emuconsole.c (grub_console_term_output): Likewise.
+       * grub-core/term/arc/console.c (grub_console_term_output): Likewise.
+       * grub-core/term/efi/console.c (grub_console_term_output): Likewise.
+       * grub-core/term/gfxterm.c (grub_video_term): Likewise.
+       * grub-core/term/i386/coreboot/cbmemc.c (grub_cbmemc_term_output): Likewise.
+       * grub-core/term/i386/pc/console.c (grub_console_term_output): Likewise.
+       * grub-core/term/i386/pc/vga_text.c (grub_vga_text_term): Likewise.
+       * grub-core/term/ieee1275/console.c (grub_console_term_output): Likewise.
+       * grub-core/term/morse.c (grub_audio_term_output): Likewise.
+       * grub-core/term/serial.c (grub_serial_term_output): Likewise.
+       * grub-core/term/spkmodem.c (grub_spkmodem_term_output): Likewise.
+       * grub-core/term/uboot/console.c (uboot_console_term_output): Likewise.
+
 2013-10-22  Vladimir Serbinenko  <phcoder@gmail.com>
 
        Verify signatures of signatures unless --skip-sig is specified.
index c8ce7c951767797666985fce06174b0c41560910..abd54bae4e09f013139447606bf6dcdd2b49d53d 100644 (file)
@@ -2135,3 +2135,8 @@ module = {
   name = tr;
   common = commands/tr.c;
 };
+
+module = {
+  name = progress;
+  common = lib/progress.c;
+};
index 58a8427d5dd6d050ead83efeaef2a15d375327c2..c79ec433a95acafe75517b8da284aa09388eafea 100644 (file)
@@ -243,10 +243,17 @@ static grub_ssize_t
 grub_cbfs_read (grub_file_t file, char *buf, grub_size_t len)
 {
   struct grub_archelp_data *data;
+  grub_ssize_t ret;
 
   data = file->data;
-  return (grub_disk_read (data->disk, 0, data->dofs + file->offset,
-                         len, buf)) ? -1 : (grub_ssize_t) len;
+  data->disk->read_hook = file->read_hook;
+  data->disk->read_hook_data = file->read_hook_data;
+
+  ret = (grub_disk_read (data->disk, 0, data->dofs + file->offset,
+                        len, buf)) ? -1 : (grub_ssize_t) len;
+  data->disk->read_hook = 0;
+
+  return ret;
 }
 
 static grub_err_t
index 370324ceb53169ef08626e70cbdac8c2f5fc8c50..b0ae9f445cc6b91d4b5f4bc373fd8e7a8c94914b 100644 (file)
@@ -200,10 +200,17 @@ static grub_ssize_t
 grub_cpio_read (grub_file_t file, char *buf, grub_size_t len)
 {
   struct grub_archelp_data *data;
+  grub_ssize_t ret;
 
   data = file->data;
-  return (grub_disk_read (data->disk, 0, data->dofs + file->offset,
-                         len, buf)) ? -1 : (grub_ssize_t) len;
+  data->disk->read_hook = file->read_hook;
+  data->disk->read_hook_data = file->read_hook_data;
+
+  ret = (grub_disk_read (data->disk, 0, data->dofs + file->offset,
+                        len, buf)) ? -1 : (grub_ssize_t) len;
+  data->disk->read_hook = 0;
+
+  return ret;
 }
 
 static grub_err_t
index 64266686d66f895727372a3eda0e2a649140a64e..ea1817a41bc81d6b1b140e89cd188f97d6db1c50 100644 (file)
@@ -87,6 +87,9 @@ grub_file_open (const char *name)
   if (! file)
     goto fail;
 
+  file->name = grub_strdup (name);
+  grub_errno = GRUB_ERR_NONE;
+
   file->device = device;
 
   if (device->disk && file_name[0] != '/')
@@ -131,10 +134,14 @@ grub_file_open (const char *name)
   return 0;
 }
 
+grub_disk_read_hook_t grub_file_progress_hook;
+
 grub_ssize_t
 grub_file_read (grub_file_t file, void *buf, grub_size_t len)
 {
   grub_ssize_t res;
+  grub_disk_read_hook_t read_hook;
+  void *read_hook_data;
 
   if (file->offset > file->size)
     {
@@ -155,7 +162,17 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len)
 
   if (len == 0)
     return 0;
+  read_hook = file->read_hook;
+  read_hook_data = file->read_hook_data;
+  if (!file->read_hook)
+    {
+      file->read_hook = grub_file_progress_hook;
+      file->read_hook_data = file;
+      file->progress_offset = file->offset;
+    }
   res = (file->fs->read) (file, buf, len);
+  file->read_hook = read_hook;
+  file->read_hook_data = read_hook_data;
   if (res > 0)
     file->offset += res;
 
diff --git a/grub-core/lib/progress.c b/grub-core/lib/progress.c
new file mode 100644 (file)
index 0000000..8b34c6a
--- /dev/null
@@ -0,0 +1,100 @@
+/* progress.c - show loading progress */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/time.h>
+#include <grub/term.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define UPDATE_INTERVAL 800
+
+static void
+grub_file_progress_hook_real (grub_disk_addr_t sector __attribute__ ((unused)),
+                              unsigned offset __attribute__ ((unused)),
+                              unsigned length, void *data)
+{
+  grub_uint64_t now = grub_get_time_ms ();
+  static grub_uint64_t last_progress_update_time;
+  grub_file_t file = data;
+  file->progress_offset += length;
+
+  if (((now - last_progress_update_time > UPDATE_INTERVAL) &&
+       (file->progress_offset - file->offset > 0)) ||
+      (file->progress_offset == file->size))
+    {
+      char buffer[80];
+      struct grub_term_output *term;
+      char *partial_file_name = grub_strrchr (file->name, '/') + 1;
+
+      grub_uint64_t current_speed = grub_divmod64 ((file->progress_offset -
+                                                    file->last_progress_offset)
+                                                   * 100ULL * 1000ULL,
+                                                   now - file->last_progress_time, 0);
+
+      file->estimated_speed = (file->estimated_speed + current_speed) >> 1;
+
+      grub_snprintf (buffer, sizeof (buffer), "      [ %.20s  %s  %llu%%  ",
+                     partial_file_name,
+                     grub_get_human_size (file->progress_offset,
+                                          GRUB_HUMAN_SIZE_NORMAL),
+                     (100 * file->progress_offset) / file->size);
+
+      char *ptr = buffer + grub_strlen (buffer);
+      grub_snprintf (ptr, sizeof (buffer) - (ptr - buffer), "%s ]",
+                     grub_get_human_size (file->estimated_speed,
+                                          GRUB_HUMAN_SIZE_SPEED));
+
+      grub_uint16_t len = grub_strlen (buffer);
+      FOR_ACTIVE_TERM_OUTPUTS (term)
+        {
+          if (term->progress_update_counter++ > term->progress_update_divisor ||
+              (file->progress_offset == file->size &&
+               term->progress_update_divisor != (unsigned) GRUB_PROGRESS_NO_UPDATE))
+            {
+              struct grub_term_coordinate old_pos = grub_term_getxy (term);
+              struct grub_term_coordinate new_pos = old_pos;
+              new_pos.x = grub_term_width (term) - len - 1;
+
+              grub_term_gotoxy (term, new_pos);
+              grub_puts_terminal (buffer, term);
+              grub_term_gotoxy (term, old_pos);
+
+              term->progress_update_counter = 0;
+            }
+        }
+
+      file->last_progress_offset = file->progress_offset;
+      file->last_progress_time = now;
+      last_progress_update_time = now;
+    }
+}
+
+GRUB_MOD_INIT(progress)
+{
+  grub_file_progress_hook = grub_file_progress_hook_real;
+}
+
+GRUB_MOD_FINI(progress)
+{
+  grub_file_progress_hook = 0;
+}
index da50cbffeafa126ed8fb77eac08de4475ac956b8..6d143fb51777159318ffde5ca95ecd9a1ef347a9 100644 (file)
@@ -1536,6 +1536,8 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
          len -= amount;
          total += amount;
          file->device->net->offset += amount;
+         if (grub_file_progress_hook)
+           grub_file_progress_hook (0, 0, amount, file);
          if (buf)
            {
              grub_memcpy (ptr, nb->data, amount);
index 53aa28500efec0fd260f7cc352f983dc619a65e6..9c1b5505b3f0c3bf178100b0486df76e77cfcb2f 100644 (file)
@@ -149,6 +149,7 @@ static struct grub_term_output grub_console_term_output =
     .setcolorstate = grub_terminfo_setcolorstate,
     .setcursor = grub_terminfo_setcursor,
     .data = &grub_console_terminfo_output,
+    .progress_update_divisor = GRUB_PROGRESS_FAST
   };
 
 void
index f3414eff7e07d2ba103c1190451d867c5dc81bf1..a2acf2637f8baa102fceb1a06d679198cfe4a2ff 100644 (file)
@@ -283,7 +283,8 @@ static struct grub_term_output grub_console_term_output =
     .cls = grub_console_cls,
     .setcolorstate = grub_console_setcolorstate,
     .setcursor = grub_console_setcursor,
-    .flags = GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS
+    .flags = GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS,
+    .progress_update_divisor = GRUB_PROGRESS_FAST
   };
 
 void
index 87a65cc169f5818a11e7cd6aa56544433068d1d9..330a9f7eeab91abbe206ea1f60e1b17e57c4fb8e 100644 (file)
@@ -188,6 +188,7 @@ static struct grub_term_output grub_console_term_output =
     .setcursor = grub_terminfo_setcursor,
     .flags = GRUB_TERM_CODE_TYPE_ASCII,
     .data = &grub_console_terminfo_output,
+    .progress_update_divisor = GRUB_PROGRESS_FAST
   };
 
 void
index e6bb50d6574fadbe313ad8d3510dc937c19a02ed..a000fa64818929b935fd657bf1b508ad3a2e3c4f 100644 (file)
@@ -276,7 +276,8 @@ static struct grub_term_output grub_console_term_output =
     .cls = grub_console_cls,
     .setcolorstate = grub_console_setcolorstate,
     .setcursor = grub_console_setcursor,
-    .flags = GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS
+    .flags = GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS,
+    .progress_update_divisor = GRUB_PROGRESS_FAST
   };
 
 void
index 83b42cf504d69fcb7e64ec6afb4c4ef36c5fc085..ce0bce7050a6d7f9c17472758c1782b059ced49b 100644 (file)
@@ -1108,6 +1108,7 @@ static struct grub_term_output grub_video_term =
     .refresh = grub_gfxterm_refresh,
     .fullscreen = grub_gfxterm_fullscreen,
     .flags = GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS,
+    .progress_update_divisor = GRUB_PROGRESS_SLOW,
     .next = 0
   };
 
index 2a0877ce016820c2b5a92e1aaf7a32eef5522ae5..25e64a05c03286f644b39398e9e68cbdde333510 100644 (file)
@@ -68,6 +68,7 @@ static struct grub_term_output grub_cbmemc_term_output =
     .setcursor = grub_terminfo_setcursor,
     .flags = GRUB_TERM_CODE_TYPE_ASCII,
     .data = &grub_cbmemc_terminfo_output,
+    .progress_update_divisor = GRUB_PROGRESS_NO_UPDATE
   };
 
 static int
index a727653d709a1360773e99102e316cba8d05be5b..28de46b576a667fd40c5852b16a4bcc3ea681849 100644 (file)
@@ -292,6 +292,7 @@ static struct grub_term_output grub_console_term_output =
     .setcolorstate = grub_console_setcolorstate,
     .setcursor = grub_console_setcursor,
     .flags = GRUB_TERM_CODE_TYPE_CP437,
+    .progress_update_divisor = GRUB_PROGRESS_FAST
   };
 
 void
index 33834bf74d3042fe95b4050511d8684715c9119d..1234e6100c17230e09c462f4593957e027c04a58 100644 (file)
@@ -267,6 +267,7 @@ static struct grub_term_output grub_vga_text_term =
     .setcolorstate = grub_vga_text_setcolorstate,
     .setcursor = grub_vga_text_setcursor,
     .flags = GRUB_TERM_CODE_TYPE_CP437,
+    .progress_update_divisor = GRUB_PROGRESS_FAST
   };
 
 /* FIXME: this is was too spaghetti.  */
index 17010e744694cbaae5138772b3bf8a6c7b716a70..7e797a7d444551381b52fbb164103a0826f57aec 100644 (file)
@@ -236,6 +236,7 @@ static struct grub_term_output grub_console_term_output =
     .setcursor = grub_console_setcursor,
     .flags = GRUB_TERM_CODE_TYPE_ASCII,
     .data = &grub_console_terminfo_output,
+    .progress_update_divisor = GRUB_PROGRESS_FAST
   };
 
 void
index ba84dfe145d83c7c9490d2c8b8d6dd7b457783a9..13b8e863e339b2c1c1205312d655fee7af004a6a 100644 (file)
@@ -118,7 +118,8 @@ static struct grub_term_output grub_audio_term_output =
    .cls = (void *) dummy,
    .setcolorstate = (void *) dummy,
    .setcursor = (void *) dummy,
-   .flags = GRUB_TERM_CODE_TYPE_ASCII | GRUB_TERM_DUMB
+   .flags = GRUB_TERM_CODE_TYPE_ASCII | GRUB_TERM_DUMB,
+   .progress_update_divisor = GRUB_PROGRESS_NO_UPDATE
   };
 
 GRUB_MOD_INIT (morse)
index ac1fb8394be9fd917f9461f4786a5062a4546978..1c928fe785623726ef2e3027f2b5ffc2789b00e2 100644 (file)
@@ -123,6 +123,7 @@ static struct grub_term_output grub_serial_term_output =
   .setcursor = grub_terminfo_setcursor,
   .flags = GRUB_TERM_CODE_TYPE_ASCII,
   .data = &grub_serial_terminfo_output,
+  .progress_update_divisor = GRUB_PROGRESS_SLOW
 };
 
 \f
index 7d4ead356752a5ba2d49edc17a5c47120c08a7ab..75c8a0f82647aa3938f47c908907f80410ef51f1 100644 (file)
@@ -126,6 +126,7 @@ static struct grub_term_output grub_spkmodem_term_output =
     .setcursor = grub_terminfo_setcursor,
     .flags = GRUB_TERM_CODE_TYPE_ASCII,
     .data = &grub_spkmodem_terminfo_output,
+    .progress_update_divisor = GRUB_PROGRESS_NO_UPDATE
   };
 
 GRUB_MOD_INIT (spkmodem)
index 8bf1b3cee01ccd3c94ef1a8acd6a9ed127379387..dfdbe990948d3981921750c01038f4198dd9957c 100644 (file)
@@ -95,6 +95,7 @@ static struct grub_term_output uboot_console_term_output = {
   .setcursor = uboot_console_setcursor,
   .flags = GRUB_TERM_CODE_TYPE_ASCII,
   .data = &uboot_console_terminfo_output,
+  .progress_update_divisor = GRUB_PROGRESS_FAST
 };
 
 void
index 8003985e83b8ce45a6f86f5f29732c4b73589fa6..f8ae8d9a891635a90565ebb3f08b69334a3d51a4 100644 (file)
@@ -28,6 +28,9 @@
 /* File description.  */
 struct grub_file
 {
+  /* File name.  */
+  char *name;
+
   /* The underlying device.  */
   grub_device_t device;
 
@@ -36,6 +39,12 @@ struct grub_file
 
   /* The current offset.  */
   grub_off_t offset;
+  grub_off_t progress_offset;
+
+  /* Progress info. */
+  grub_uint64_t last_progress_time;
+  grub_off_t last_progress_offset;
+  grub_uint64_t estimated_speed;
 
   /* The file size.  */
   grub_off_t size;
@@ -54,6 +63,8 @@ struct grub_file
 };
 typedef struct grub_file *grub_file_t;
 
+extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
+
 /* Filters with lower ID are executed first.  */
 typedef enum grub_file_filter_id
   {
index 9ca0c57a971ae4f39863b8f1036473e620f578da..9d755a965c0b99357281b6f7993fb811eb9ae058 100644 (file)
 #define GRUB_TERM_TAB          '\t'
 #define GRUB_TERM_BACKSPACE    '\b'
 
+#define GRUB_PROGRESS_NO_UPDATE -1
+#define GRUB_PROGRESS_FAST      0
+#define GRUB_PROGRESS_SLOW      2
+
 #ifndef ASM_FILE
 
 #include <grub/err.h>
@@ -215,6 +219,10 @@ struct grub_term_output
   /* The feature flags defined above.  */
   grub_uint32_t flags;
 
+  /* Progress data. */
+  grub_uint32_t progress_update_divisor;
+  grub_uint32_t progress_update_counter;
+
   void *data;
 };
 typedef struct grub_term_output *grub_term_output_t;