Coverage Report

Created: 2025-11-11 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/libblkid/src/superblocks/ddf_raid.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3
 *
4
 * Inspired by libvolume_id by
5
 *     Kay Sievers <kay.sievers@vrfy.org>
6
 *
7
 * This file may be redistributed under the terms of the
8
 * GNU Lesser General Public License.
9
 */
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <unistd.h>
13
#include <string.h>
14
#include <stdint.h>
15
16
#include "crc32.h"
17
#include "superblocks.h"
18
19
/* http://www.snia.org/standards/home */
20
#define DDF_GUID_LENGTH     24
21
#define DDF_REV_LENGTH      8
22
#define DDF_MAGIC     0xDE11DE11
23
24
25
struct ddf_header {
26
  uint32_t  signature;
27
  uint32_t  crc;
28
  uint8_t   guid[DDF_GUID_LENGTH];
29
  char    ddf_rev[8]; /* 01.02.00 */
30
  uint32_t  seq;    /* starts at '1' */
31
  uint32_t  timestamp;
32
  uint8_t   openflag;
33
  uint8_t   foreignflag;
34
  uint8_t   enforcegroups;
35
  uint8_t   pad0;   /* 0xff */
36
  uint8_t   pad1[12]; /* 12 * 0xff */
37
  /* 64 bytes so far */
38
  uint8_t   header_ext[32]; /* reserved: fill with 0xff */
39
  uint64_t  primary_lba;
40
  uint64_t  secondary_lba;
41
  uint8_t   type;
42
  uint8_t   pad2[3];  /* 0xff */
43
  uint32_t  workspace_len;  /* sectors for vendor space -
44
           * at least 32768(sectors) */
45
  uint64_t  workspace_lba;
46
  uint16_t  max_pd_entries; /* one of 15, 63, 255, 1023, 4095 */
47
  uint16_t  max_vd_entries; /* 2^(4,6,8,10,12)-1 : i.e. as above */
48
  uint16_t  max_partitions; /* i.e. max num of configuration
49
             record entries per disk */
50
  uint16_t  config_record_len; /* 1 +ROUNDUP(max_primary_element_entries
51
                   *12/512) */
52
  uint16_t  max_primary_element_entries; /* 16, 64, 256, 1024, or 4096 */
53
  uint8_t   pad3[54]; /* 0xff */
54
  /* 192 bytes so far */
55
  uint32_t  controller_section_offset;
56
  uint32_t  controller_section_length;
57
  uint32_t  phys_section_offset;
58
  uint32_t  phys_section_length;
59
  uint32_t  virt_section_offset;
60
  uint32_t  virt_section_length;
61
  uint32_t  config_section_offset;
62
  uint32_t  config_section_length;
63
  uint32_t  data_section_offset;
64
  uint32_t  data_section_length;
65
  uint32_t  bbm_section_offset;
66
  uint32_t  bbm_section_length;
67
  uint32_t  diag_space_offset;
68
  uint32_t  diag_space_length;
69
  uint32_t  vendor_offset;
70
  uint32_t  vendor_length;
71
  /* 256 bytes so far */
72
  uint8_t   pad4[256];  /* 0xff */
73
} __attribute__((packed));
74
75
static int ddf_verify_csum(blkid_probe pr, const struct ddf_header *ddf)
76
0
{
77
0
  uint32_t expected, crc;
78
79
0
  expected = be32_to_cpu(ddf->crc);
80
81
0
  crc = ul_crc32_exclude_offset(0,
82
0
              (const unsigned char *)ddf, sizeof(*ddf),
83
0
              offsetof(__typeof__(*ddf), crc),
84
0
              sizeof_member(__typeof__(*ddf), crc),
85
0
              0xff);
86
87
0
  return blkid_probe_verify_csum(pr, crc, expected);
88
0
}
89
90
static int probe_ddf(blkid_probe pr,
91
    const struct blkid_idmag *mag __attribute__((__unused__)))
92
6.12k
{
93
6.12k
  int hdrs[] = { 1, 257 };
94
6.12k
  size_t i;
95
6.12k
  const struct ddf_header *ddf = NULL;
96
6.12k
  char version[DDF_REV_LENGTH + 1];
97
6.12k
  uint64_t off = 0, lba;
98
99
18.3k
  for (i = 0; i < ARRAY_SIZE(hdrs); i++) {
100
12.2k
    off = ((pr->size / 0x200) - hdrs[i]) * 0x200;
101
102
12.2k
    ddf = (const struct ddf_header *) blkid_probe_get_buffer(pr,
103
12.2k
          off,
104
12.2k
          sizeof(struct ddf_header));
105
12.2k
    if (!ddf)
106
0
      return errno ? -errno : 1;
107
12.2k
    if (ddf->signature == cpu_to_be32(DDF_MAGIC) && ddf_verify_csum(pr, ddf))
108
0
      break;
109
12.2k
    ddf = NULL;
110
12.2k
  }
111
112
6.12k
  if (!ddf)
113
6.12k
    return 1;
114
115
0
  lba = be64_to_cpu(ddf->primary_lba);
116
117
0
  if (lba > 0) {
118
    /* check primary header */
119
0
    const unsigned char *buf;
120
121
0
    buf = blkid_probe_get_buffer(pr,
122
0
          lba << 9, sizeof(ddf->signature));
123
0
    if (!buf)
124
0
      return errno ? -errno : 1;
125
126
0
    if (memcmp(buf, &ddf->signature, 4) != 0)
127
0
      return 1;
128
0
  }
129
130
0
  blkid_probe_strncpy_uuid(pr, ddf->guid, sizeof(ddf->guid));
131
132
0
  memcpy(version, ddf->ddf_rev, sizeof(ddf->ddf_rev));
133
0
  *(version + sizeof(ddf->ddf_rev)) = '\0';
134
135
0
  if (blkid_probe_set_version(pr, version) != 0)
136
0
    return 1;
137
0
  if (blkid_probe_set_magic(pr, off,
138
0
      sizeof(ddf->signature),
139
0
      (const unsigned char *) &ddf->signature))
140
0
    return 1;
141
0
  return 0;
142
0
}
143
144
const struct blkid_idinfo ddfraid_idinfo = {
145
  .name   = "ddf_raid_member",
146
  .usage    = BLKID_USAGE_RAID,
147
  .minsz    = 0x30000,
148
  .probefunc  = probe_ddf,
149
  .magics   = BLKID_NONE_MAGIC
150
};
151
152