Nowe posty

Autor Wątek: Jak zmienić lokalizację zapasowej tablicy GPT?  (Przeczytany 3075 razy)

Offline overcq

  • Nowy na forum
  • *
  • Wiadomości: 32
    • Zobacz profil
    • ‛overcq’
Jak zmienić lokalizację zapasowej tablicy GPT?
« dnia: 2024-01-05, 17:40:33 »
Mam już dość długo używany dysk HDD. I od niedawna, od czasu ostatniej modyfikacji tablicy partycji, pojawia się taki komunikat po uruchomieniu
fdisk -l /dev/sda
The backup GPT table is corrupt, but the primary appears OK, so that will be used.
Po czym następuje poprawne wyświetlenie zawartości tablicy partycji.
Skopiowałem drugi sektor dysku programem “dd” i sprawdziłem, co znajduje się w 8 bajtach pod adresem 0x20 czyli “Backup LBA”, zgodnie z Wikipedią. I jest tam adres 0x74706daf, który wskazuje prawdopodobnie na ostatni sektor dysku albo nawet poza dysk.

Czy jest jakieś narzędzie, które pozwala zmienić lokalizację zapasowej tablicy GPT, tak by była w nie uszkodzonym sektorze (lub w granicach dysku) bez konieczności ponownej instalacji systemu?

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3062
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
Odp: Jak zmienić lokalizację zapasowej tablicy GPT?
« Odpowiedź #1 dnia: 2024-01-06, 11:24:18 »
Robisz odwrotnie do tego, co napisałem Zielonemu:

Instrukcja jest tutaj i tutaj.

W skrócie:

1. gdisk /dev/nvme0n1
2. Powinno pojawić się, że główna tablica (main) jest "OK" a zapasowa tablica (backup) ma "ERROR"
3. Dajesz polecenie r (recovery)
4. Wybierasz opcję d (use main GPT header) (tu jest różnica względem problemu Zielonego - ty masz dobry main, on miał dobry backup)
5. Poleceniem p wyświetlasz odzyskaną tablicę.
6. Jak wszystko jest ok, poleceniem w zapisujesz odzyskaną tablicę na dysk.
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy

Offline overcq

  • Nowy na forum
  • *
  • Wiadomości: 32
    • Zobacz profil
    • ‛overcq’
Odp: Jak zmienić lokalizację zapasowej tablicy GPT?
« Odpowiedź #2 dnia: 2024-01-06, 11:42:54 »
Problem był w tym, że zapasowa tablica partycji nie mogła być zapisana na dysk z powodu błędu zapisu sektora.

Rozwiązałem to ręcznie: przesunąłem (skopiowałem z podstawowej) zapasową tablicę partycji wstecz o kilkadziesiąt sektorów w obszarze nie używanym przez ostatnią partycję na dysku (jest taki obszar ok. 700 kB), zmodyfikowałem ‘header’ zapasowej tablicy partycji, w którym ustawiłem nową lokalizację tablicy partycji i sumę kontrolną ‘headera’.

Wykorzystałem następujący skrypt, gdzie “binary-read” i “binary-write” to programy pakietu binary-change:
Kod: shell [Zaznacz]

#!/bin/bash
#*******************************************************************************
trap 'rm "$header" "$header_crc32" "$table"' EXIT
header="$( mktemp )"
header_crc32="$( mktemp )"
table="$( mktemp )"
#===============================================================================
dd if=/dev/sda of="$header" bs=512 skip=1 count=1
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
header_sector=$( binary-read -f "$header" -p 0x20 -l -s 8 )
table_sector=$(( $header_sector - 32 - 32 ))
partition_last_sector=$( fdisk -l /dev/sda | tail -n 2 | head -n 1 | sed -e 's`^[^ ][^ ]*  *[0-9][0-9]*  *\([0-9][0-9]*\).*$`\1`' )
if [ $header_sector -le $partition_last_sector -o $table_sector -le $partition_last_sector ]; then
    echo 'Header or table sector too low'
    exit 1
fi
binary-write -f "$header" -p 0x10 -l -s 4 -d 0 -p 0x30 -l -s 8 -d $(( $table_sector - 1 ))
dd if="$header" of="$header_crc32" bs=92 count=1
crc32=$( crc32 "$header_crc32" )
binary-write -f "$header" -p 0x10 -l -s 4 -d 0x$crc32
dd if="$header" of=/dev/sda bs=512 seek=1
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dd if=/dev/sda of="$table" bs=512 skip=2 count=32
binary-write -f "$header" -p 0x10 -l -s 4 -d 0 -p 0x18 -l -s 8 -d $header_sector -p 0x20 -l -s 8 -d 1 -p 0x48 -l -s 8 -d $table_sector
dd if="$header" of="$header_crc32" bs=92 count=1
crc32=$( crc32 "$header_crc32" )
binary-write -f "$header" -p 0x10 -l -s 4 -d 0x$crc32
dd if="$header" of=/dev/sda bs=512 seek=$header_sector
dd if="$table" of=/dev/sda bs=512 seek=$table_sector
gdisk -l /dev/sda
#*******************************************************************************
« Ostatnia zmiana: 2024-01-07, 14:41:41 wysłana przez overcq »