xref: /spdk/scripts/spdk-gpt.py (revision 3a39d90b03f7581d60716e3e9cf4dbcf7c48b08a)
1#!/usr/bin/env python3
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2021 Intel Corporation
4#  All rights reserved.
5#
6
7import argparse
8import os
9import stat
10import struct
11
12
13def block_exists(block):
14    return os.path.exists(block) and stat.S_ISBLK(os.stat(block).st_mode)
15
16
17def lbsize(block):
18    if not os.path.exists("/sys/block/%s/queue/logical_block_size" % block):
19        return 512
20
21    with open("/sys/block/%s/queue/logical_block_size" % block) as lbs:
22        return int(lbs.read())
23
24
25def readb(block, offset, length, format="Q"):
26    b = os.open(block, os.O_RDONLY)
27    os.lseek(b, offset, os.SEEK_SET)
28    data = os.read(b, length)
29    os.close(b)
30    return struct.unpack(format, data)[0]
31
32
33def is_spdk_gpt(block, entry):
34    block_path = "/dev/" + block
35
36    if not block_exists(block_path):
37        print("%s is not a block device" % block)
38        return False
39
40    disk_lbsize = lbsize(block)
41    gpt_sig = 0x5452415020494645  # EFI PART
42    spdk_guid = [0x7c5222bd, 0x8f5d, 0x4087, 0x9c00, 0xbf9843c7b58c]
43    spdk_guid2 = [0x6527994e, 0x2c5a, 0x4eec, 0x9613, 0x8f5944074e8b]
44
45    if readb(block_path, disk_lbsize, 8) != gpt_sig:
46        print("No valid GPT data, bailing")
47        return False
48
49    part_entry_lba = disk_lbsize * readb(block_path, disk_lbsize + 72, 8)
50    part_entry_lba = part_entry_lba + (entry - 1) * 128
51
52    guid = [
53        readb(block_path, part_entry_lba, 4, "I"),
54        readb(block_path, part_entry_lba + 4, 2, "H"),
55        readb(block_path, part_entry_lba + 6, 2, "H"),
56        readb(block_path, part_entry_lba + 8, 2, ">H"),
57        readb(block_path, part_entry_lba + 10, 8, ">Q") >> 16
58    ]
59
60    return guid == spdk_guid or guid == spdk_guid2
61
62
63if __name__ == "__main__":
64    parser = argparse.ArgumentParser(description='Checks if SPDK GUID is present on given block device')
65    parser.add_argument('block', type=str, help='block device to check')
66    parser.add_argument('-e', '--entry', dest='entry', help='GPT partition entry',
67                        required=False, type=int, default=1)
68    args = parser.parse_args()
69    try:
70        if is_spdk_gpt(args.block.replace("/dev/", ""), args.entry):
71            exit(0)
72        exit(1)
73    except Exception as e:
74        print("Failed to read GPT data from %s (%s)" % (args.block, e))
75        exit(1)
76