blob: ffe408fead0cdf8ca137be725540e35aa122572a [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * fs/partitions/check.c
4 *
5 * Code extracted from drivers/block/genhd.c
6 * Copyright (C) 1991-1998 Linus Torvalds
7 * Re-organised Feb 1998 Russell King
8 *
9 * We now have independent partition support from the
10 * block drivers, which allows all the partition code to
11 * be grouped in one location, and it to be mostly self
12 * contained.
13 *
14 * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
15 */
16
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
Ming Leiac2e5322013-02-27 17:05:19 -080018#include <linux/vmalloc.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/ctype.h>
Jerome Marchand6f2576af2008-02-08 11:04:35 +010020#include <linux/genhd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021
22#include "check.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
24#include "acorn.h"
25#include "amiga.h"
26#include "atari.h"
27#include "ldm.h"
28#include "mac.h"
29#include "msdos.h"
30#include "osf.h"
31#include "sgi.h"
32#include "sun.h"
33#include "ibm.h"
34#include "ultrix.h"
35#include "efi.h"
Bob Copeland0e6e1db2006-01-16 22:14:20 -080036#include "karma.h"
Philippe De Muyter19d0e8c2007-05-08 00:29:15 -070037#include "sysv68.h"
Cai Zhiyongbab55412013-09-11 14:20:09 -070038#include "cmdline.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Linus Torvalds1da177e2005-04-16 15:20:36 -070040int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
41
Tejun Heo1493bf22010-05-15 20:09:30 +020042static int (*check_part[])(struct parsed_partitions *) = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 /*
44 * Probe partition formats with tables at disk address 0
45 * that also have an ADFS boot block at 0xdc0.
46 */
47#ifdef CONFIG_ACORN_PARTITION_ICS
48 adfspart_check_ICS,
49#endif
50#ifdef CONFIG_ACORN_PARTITION_POWERTEC
51 adfspart_check_POWERTEC,
52#endif
53#ifdef CONFIG_ACORN_PARTITION_EESOX
54 adfspart_check_EESOX,
55#endif
56
57 /*
58 * Now move on to formats that only have partition info at
59 * disk address 0xdc0. Since these may also have stale
60 * PC/BIOS partition tables, they need to come before
61 * the msdos entry.
62 */
63#ifdef CONFIG_ACORN_PARTITION_CUMANA
64 adfspart_check_CUMANA,
65#endif
66#ifdef CONFIG_ACORN_PARTITION_ADFS
67 adfspart_check_ADFS,
68#endif
69
Cai Zhiyongbab55412013-09-11 14:20:09 -070070#ifdef CONFIG_CMDLINE_PARTITION
71 cmdline_partition,
72#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#ifdef CONFIG_EFI_PARTITION
74 efi_partition, /* this must come before msdos */
75#endif
76#ifdef CONFIG_SGI_PARTITION
77 sgi_partition,
78#endif
79#ifdef CONFIG_LDM_PARTITION
80 ldm_partition, /* this must come before msdos */
81#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070082#ifdef CONFIG_MSDOS_PARTITION
83 msdos_partition,
84#endif
85#ifdef CONFIG_OSF_PARTITION
86 osf_partition,
87#endif
88#ifdef CONFIG_SUN_PARTITION
89 sun_partition,
90#endif
91#ifdef CONFIG_AMIGA_PARTITION
92 amiga_partition,
93#endif
94#ifdef CONFIG_ATARI_PARTITION
95 atari_partition,
96#endif
97#ifdef CONFIG_MAC_PARTITION
98 mac_partition,
99#endif
100#ifdef CONFIG_ULTRIX_PARTITION
101 ultrix_partition,
102#endif
103#ifdef CONFIG_IBM_PARTITION
104 ibm_partition,
105#endif
Bob Copeland0e6e1db2006-01-16 22:14:20 -0800106#ifdef CONFIG_KARMA_PARTITION
107 karma_partition,
108#endif
Philippe De Muyter19d0e8c2007-05-08 00:29:15 -0700109#ifdef CONFIG_SYSV68_PARTITION
110 sysv68_partition,
111#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 NULL
113};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
Ming Leiac2e5322013-02-27 17:05:19 -0800115static struct parsed_partitions *allocate_partitions(struct gendisk *hd)
116{
117 struct parsed_partitions *state;
118 int nr;
119
120 state = kzalloc(sizeof(*state), GFP_KERNEL);
121 if (!state)
122 return NULL;
123
124 nr = disk_max_parts(hd);
Kees Cookfad953c2018-06-12 14:27:37 -0700125 state->parts = vzalloc(array_size(nr, sizeof(state->parts[0])));
Ming Leiac2e5322013-02-27 17:05:19 -0800126 if (!state->parts) {
127 kfree(state);
128 return NULL;
129 }
130
131 state->limit = nr;
132
133 return state;
134}
135
136void free_partitions(struct parsed_partitions *state)
137{
138 vfree(state->parts);
139 kfree(state);
140}
141
Al Viro94ea4152011-09-16 00:45:36 -0400142struct parsed_partitions *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143check_partition(struct gendisk *hd, struct block_device *bdev)
144{
145 struct parsed_partitions *state;
Suzuki K P57881dd2006-12-06 20:35:16 -0800146 int i, res, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Ming Leiac2e5322013-02-27 17:05:19 -0800148 state = allocate_partitions(hd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 if (!state)
150 return NULL;
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700151 state->pp_buf = (char *)__get_free_page(GFP_KERNEL);
152 if (!state->pp_buf) {
Ming Leiac2e5322013-02-27 17:05:19 -0800153 free_partitions(state);
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700154 return NULL;
155 }
156 state->pp_buf[0] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
Tejun Heo1493bf22010-05-15 20:09:30 +0200158 state->bdev = bdev;
Greg Kroah-Hartmana2964182005-06-20 21:15:16 -0700159 disk_name(hd, 0, state->name);
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700160 snprintf(state->pp_buf, PAGE_SIZE, " %s:", state->name);
Greg Kroah-Hartmana2964182005-06-20 21:15:16 -0700161 if (isdigit(state->name[strlen(state->name)-1]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 sprintf(state->name, "p");
Greg Kroah-Hartmana2964182005-06-20 21:15:16 -0700163
Suzuki K P57881dd2006-12-06 20:35:16 -0800164 i = res = err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 while (!res && check_part[i]) {
Ming Leiac2e5322013-02-27 17:05:19 -0800166 memset(state->parts, 0, state->limit * sizeof(state->parts[0]));
Tejun Heo1493bf22010-05-15 20:09:30 +0200167 res = check_part[i++](state);
Suzuki K P57881dd2006-12-06 20:35:16 -0800168 if (res < 0) {
169 /* We have hit an I/O error which we don't report now.
170 * But record it, and let the others do their job.
171 */
172 err = res;
173 res = 0;
174 }
175
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 }
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700177 if (res > 0) {
178 printk(KERN_INFO "%s", state->pp_buf);
179
180 free_page((unsigned long)state->pp_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 return state;
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700182 }
Tejun Heob403a982010-05-15 20:09:31 +0200183 if (state->access_beyond_eod)
184 err = -ENOSPC;
suzuki9bebff62007-03-07 20:41:24 -0800185 if (err)
Suzuki K P57881dd2006-12-06 20:35:16 -0800186 /* The partition is unrecognized. So report I/O errors if there were any */
187 res = err;
Boaz Harroshbb5c3cd2015-01-22 14:39:20 +0200188 if (res) {
189 if (warn_no_part)
190 strlcat(state->pp_buf,
191 " unable to read partition table\n", PAGE_SIZE);
192 printk(KERN_INFO "%s", state->pp_buf);
193 }
Alexey Dobriyan9c867fb2010-08-10 18:03:14 -0700194
195 free_page((unsigned long)state->pp_buf);
Ming Leiac2e5322013-02-27 17:05:19 -0800196 free_partitions(state);
Suzuki Kp5127d002006-12-06 20:35:14 -0800197 return ERR_PTR(res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198}