Chienomi

grub_calloc not foundによる起動不能からの回復

Live With Linux::trouble shooting

割とあるトラブルのようだが、適当な解説が見当たらないので、 初心者にもわかりやすいように触れておく。

なお、私が遭遇したタイミングは

  • ディスクを別の(同じ構成で起動可能な)システムに移植
  • BIOSをアップデート

であった。

そもそもgrub_callocとはなにか

Grubのメモリ確保用関数で、mm.cで定義されている。

なぜこいつがよくnot foundになるのかはよくわからない。

/*
 * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
 * integer overflow.
 */
void *
grub_calloc (grub_size_t nmemb, grub_size_t size)
{
  void *ret;
  grub_size_t sz = 0;

  if (grub_mul (nmemb, size, &sz))
    {
      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
      return NULL;
    }

  ret = grub_memalign (0, sz);
  if (!ret)
    return NULL;

  grub_memset (ret, 0, sz);
  return ret;
}

対応を簡単に言うと

Grubを再インストールする。

実手順

x86_64なEFIシステムを前提として解説する。

まず、ターゲットシステム上で他のLinuxシステムを起動する。 これは、インストールに使ったライブディスクでもいいし、USBディスクにインストールされたLinuxシステムでも良い。

起動したらまずルートファイルシステムをマウントする。 まずはシステム上でルートを獲得する。

$ sudo bash -l
# 

ルートファイルシステムがLUKSで暗号化されている場合、これを解除する必要がある。 まずはディスクを確認しよう。

# parted -l

ルートファイルシステムを含むパーティションを確認したら、それをマップする。 nvme0n1p2は適宜読み替えること。

# cryptsetup luksOpen /dev/nvme0n1p2 rescueroot

マップできたらこれをマウントする。 /dev/mapper/rescuerootはLUKSを使っていないのであれば、/dev/nvme0n1p2のようになるだろう。

# mount /dev/mapper/rescueroot /mnt

続いてEFI bootディレクトリをマウントする。 通常、ルートファイルシステムを持つディスクの第一パーティションである。 これもparted -lを用いて確認すること。

また、私のシステムだとEFIディレクトリは/boot/efiになっている。 これはManjaroの仕様だが、そうでないかもしれない。/bootの下にはあるはずなので、ターゲットシステムと同じ環境であるならばmount | grep bootして確認すると良い。これで/boot/efiであればターゲットシステムも/boot/efiである(つまりレスキューシステムから見ると/mnt/boot/efiである)はずだ。 そうでない場合、ls /mnt/bootして内容を確認する。 もし/mnt/boot自体がEFIディレクトリなのであれば、現時点で/mnt/bootは空であるはずだ。そうでない場合、/mnt/boot/efiのような空ディレクトリが存在するだろう。そこにマウントする。

# mount /dev/nvme0n1p1 /mnt/boot/efi

/dev, /sys, /procを再帰的にバインドマウントする。 面倒を避けるためすべてバインドするが、/dev及び/sys/firmware/efiが必須である。

# mount --rbind /dev /mnt/dev
# mount --rbind /proc /mnt/proc
# monut --rbind /sys /mnt/sys

レスキューするシステムにログイン(chroot)する。

# chroot /mnt

普段rootでもZshを使っているならば、Zshログインすることもできる。 (もちろん、しなくても良い)

# zsh -l

Grubを再インストールする。基本は次のコマンドである。 /dev/nmve0n1はターゲットシステムのルートファイルシステム及びEFIファイルシステム(ESP)があるディスク全体を指定するものであり、読み替えること。

# grub-install /dev/nvme0n1 --recheck --verbose

EFIファイルシステムがデフォルト(/boot/efi)でない場合、指定する必要がある。

# grub-install /dev/nvme0n1 --efi-directory=/boot/EFI --recheck --verbose

なお、EFIファイルシステムにはEFIディレクトリがあるが、そのEFIディレクトリではなくEFIファイルシステムのルートを指定する。