history.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2009 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/mm.h>
  19. #include <grub/lib.h>
  20. #include <grub/misc.h>
  21. GRUB_EXPORT(grub_history_init);
  22. GRUB_EXPORT(grub_history_get);
  23. GRUB_EXPORT(grub_history_add);
  24. GRUB_EXPORT(grub_history_replace);
  25. GRUB_EXPORT(grub_history_used);
  26. static int hist_size;
  27. static grub_uint32_t **hist_lines = 0;
  28. static int hist_pos = 0;
  29. static int hist_end = 0;
  30. static int hist_used = 0;
  31. grub_err_t
  32. grub_history_init (int newsize)
  33. {
  34. grub_uint32_t **old_hist_lines = hist_lines;
  35. hist_lines = grub_malloc (sizeof (grub_uint32_t *) * newsize);
  36. /* Copy the old lines into the new buffer. */
  37. if (old_hist_lines)
  38. {
  39. /* Remove the lines that don't fit in the new buffer. */
  40. if (newsize < hist_used)
  41. {
  42. int i;
  43. int delsize = hist_used - newsize;
  44. hist_used = newsize;
  45. for (i = 1; i <= delsize; i++)
  46. {
  47. int pos = hist_end - i;
  48. if (pos < 0)
  49. pos += hist_size;
  50. grub_free (old_hist_lines[pos]);
  51. }
  52. hist_end -= delsize;
  53. if (hist_end < 0)
  54. hist_end += hist_size;
  55. }
  56. if (hist_pos < hist_end)
  57. grub_memmove (hist_lines, old_hist_lines + hist_pos,
  58. (hist_end - hist_pos) * sizeof (grub_uint32_t *));
  59. else if (hist_used)
  60. {
  61. /* Copy the older part. */
  62. grub_memmove (hist_lines, old_hist_lines + hist_pos,
  63. (hist_size - hist_pos) * sizeof (grub_uint32_t *));
  64. /* Copy the newer part. */
  65. grub_memmove (hist_lines + hist_size - hist_pos, old_hist_lines,
  66. hist_end * sizeof (grub_uint32_t *));
  67. }
  68. }
  69. grub_free (old_hist_lines);
  70. hist_size = newsize;
  71. hist_pos = 0;
  72. hist_end = hist_used;
  73. return 0;
  74. }
  75. /* Get the entry POS from the history where `0' is the newest
  76. entry. */
  77. grub_uint32_t *
  78. grub_history_get (int pos)
  79. {
  80. pos = (hist_pos + pos) % hist_size;
  81. return hist_lines[pos];
  82. }
  83. /* Replace the history entry on position POS with the string S. */
  84. void
  85. grub_history_set (int pos, grub_uint32_t *s, grub_size_t len)
  86. {
  87. grub_free (hist_lines[pos]);
  88. hist_lines[pos] = grub_malloc ((len + 1) * sizeof (grub_uint32_t));
  89. if (!hist_lines[pos])
  90. {
  91. grub_print_error ();
  92. grub_errno = GRUB_ERR_NONE;
  93. return ;
  94. }
  95. grub_memcpy (hist_lines[pos], s, len * sizeof (grub_uint32_t));
  96. hist_lines[pos][len] = 0;
  97. }
  98. /* Insert a new history line S on the top of the history. */
  99. void
  100. grub_history_add (grub_uint32_t *s, grub_size_t len)
  101. {
  102. /* Remove the oldest entry in the history to make room for a new
  103. entry. */
  104. if (hist_used + 1 > hist_size)
  105. {
  106. hist_end--;
  107. if (hist_end < 0)
  108. hist_end = hist_size + hist_end;
  109. grub_free (hist_lines[hist_end]);
  110. }
  111. else
  112. hist_used++;
  113. /* Move to the next position. */
  114. hist_pos--;
  115. if (hist_pos < 0)
  116. hist_pos = hist_size + hist_pos;
  117. /* Insert into history. */
  118. hist_lines[hist_pos] = NULL;
  119. grub_history_set (hist_pos, s, len);
  120. }
  121. /* Replace the history entry on position POS with the string S. */
  122. void
  123. grub_history_replace (int pos, grub_uint32_t *s, grub_size_t len)
  124. {
  125. grub_history_set ((hist_pos + pos) % hist_size, s, len);
  126. }
  127. int
  128. grub_history_used (void)
  129. {
  130. return hist_used;
  131. }