1*78444b5aSRicardo Branco /*- 2*78444b5aSRicardo Branco * SPDX-License-Identifier: BSD-2-Clause 3*78444b5aSRicardo Branco */ 4*78444b5aSRicardo Branco 5*78444b5aSRicardo Branco #include <sys/param.h> 6*78444b5aSRicardo Branco #include <sys/systm.h> 7*78444b5aSRicardo Branco #include <sys/kernel.h> 8*78444b5aSRicardo Branco #include <sys/malloc.h> 9*78444b5aSRicardo Branco 10*78444b5aSRicardo Branco #include <geom/geom.h> 11*78444b5aSRicardo Branco #include <geom/geom_dbg.h> 12*78444b5aSRicardo Branco #include <geom/label/g_label.h> 13*78444b5aSRicardo Branco 14*78444b5aSRicardo Branco /* 15*78444b5aSRicardo Branco * Taken from 16*78444b5aSRicardo Branco * https://github.com/util-linux/util-linux/blob/master/include/swapheader.h 17*78444b5aSRicardo Branco */ 18*78444b5aSRicardo Branco 19*78444b5aSRicardo Branco #define SWAP_VERSION 1 20*78444b5aSRicardo Branco #define SWAP_UUID_LENGTH 16 21*78444b5aSRicardo Branco #define SWAP_LABEL_LENGTH 16 22*78444b5aSRicardo Branco #define SWAP_SIGNATURE "SWAPSPACE2" 23*78444b5aSRicardo Branco #define SWAP_SIGNATURE_SZ (sizeof(SWAP_SIGNATURE) - 1) 24*78444b5aSRicardo Branco 25*78444b5aSRicardo Branco struct swap_header_v1_2 { 26*78444b5aSRicardo Branco char bootbits[1024]; /* Space for disklabel etc. */ 27*78444b5aSRicardo Branco uint32_t version; 28*78444b5aSRicardo Branco uint32_t last_page; 29*78444b5aSRicardo Branco uint32_t nr_badpages; 30*78444b5aSRicardo Branco unsigned char uuid[SWAP_UUID_LENGTH]; 31*78444b5aSRicardo Branco char volume_name[SWAP_LABEL_LENGTH]; 32*78444b5aSRicardo Branco uint32_t padding[117]; 33*78444b5aSRicardo Branco uint32_t badpages[1]; 34*78444b5aSRicardo Branco }; 35*78444b5aSRicardo Branco 36*78444b5aSRicardo Branco typedef union { 37*78444b5aSRicardo Branco struct swap_header_v1_2 header; 38*78444b5aSRicardo Branco struct { 39*78444b5aSRicardo Branco uint8_t reserved[PAGE_SIZE - SWAP_SIGNATURE_SZ]; 40*78444b5aSRicardo Branco char signature[SWAP_SIGNATURE_SZ]; 41*78444b5aSRicardo Branco } tail; 42*78444b5aSRicardo Branco } swhdr_t; 43*78444b5aSRicardo Branco 44*78444b5aSRicardo Branco #define sw_version header.version 45*78444b5aSRicardo Branco #define sw_volume_name header.volume_name 46*78444b5aSRicardo Branco #define sw_signature tail.signature 47*78444b5aSRicardo Branco 48*78444b5aSRicardo Branco static void 49*78444b5aSRicardo Branco g_label_swaplinux_taste(struct g_consumer *cp, char *label, size_t size) 50*78444b5aSRicardo Branco { 51*78444b5aSRicardo Branco struct g_provider *pp; 52*78444b5aSRicardo Branco swhdr_t *hdr; 53*78444b5aSRicardo Branco 54*78444b5aSRicardo Branco g_topology_assert_not(); 55*78444b5aSRicardo Branco pp = cp->provider; 56*78444b5aSRicardo Branco label[0] = '\0'; 57*78444b5aSRicardo Branco 58*78444b5aSRicardo Branco KASSERT(pp->sectorsize != 0, ("Tasting a disk with 0 sectorsize")); 59*78444b5aSRicardo Branco if ((PAGE_SIZE % pp->sectorsize) != 0) 60*78444b5aSRicardo Branco return; 61*78444b5aSRicardo Branco 62*78444b5aSRicardo Branco hdr = (swhdr_t *)g_read_data(cp, 0, PAGE_SIZE, NULL); 63*78444b5aSRicardo Branco if (hdr == NULL) 64*78444b5aSRicardo Branco return; 65*78444b5aSRicardo Branco 66*78444b5aSRicardo Branco /* Check version and magic string */ 67*78444b5aSRicardo Branco if (hdr->sw_version == SWAP_VERSION && 68*78444b5aSRicardo Branco !memcmp(hdr->sw_signature, SWAP_SIGNATURE, SWAP_SIGNATURE_SZ)) 69*78444b5aSRicardo Branco G_LABEL_DEBUG(1, "linux swap detected on %s.", pp->name); 70*78444b5aSRicardo Branco else 71*78444b5aSRicardo Branco goto exit_free; 72*78444b5aSRicardo Branco 73*78444b5aSRicardo Branco /* Check for volume label */ 74*78444b5aSRicardo Branco if (hdr->sw_volume_name[0] == '\0') 75*78444b5aSRicardo Branco goto exit_free; 76*78444b5aSRicardo Branco 77*78444b5aSRicardo Branco /* Terminate label */ 78*78444b5aSRicardo Branco hdr->sw_volume_name[sizeof(hdr->sw_volume_name) - 1] = '\0'; 79*78444b5aSRicardo Branco strlcpy(label, hdr->sw_volume_name, size); 80*78444b5aSRicardo Branco 81*78444b5aSRicardo Branco exit_free: 82*78444b5aSRicardo Branco g_free(hdr); 83*78444b5aSRicardo Branco } 84*78444b5aSRicardo Branco 85*78444b5aSRicardo Branco struct g_label_desc g_label_swaplinux = { 86*78444b5aSRicardo Branco .ld_taste = g_label_swaplinux_taste, 87*78444b5aSRicardo Branco .ld_dirprefix = "swaplinux/", 88*78444b5aSRicardo Branco .ld_enabled = 1 89*78444b5aSRicardo Branco }; 90*78444b5aSRicardo Branco 91*78444b5aSRicardo Branco G_LABEL_INIT(swaplinux, g_label_swaplinux, "Create device nodes for Linux swap"); 92