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