2b7baa0614544c578e520fcf72e795218aeaf704
[firefly-linux-kernel-4.4.55.git] / block / partitions / check.c
1 /*
2  *  fs/partitions/check.c
3  *
4  *  Code extracted from drivers/block/genhd.c
5  *  Copyright (C) 1991-1998  Linus Torvalds
6  *  Re-organised Feb 1998 Russell King
7  *
8  *  We now have independent partition support from the
9  *  block drivers, which allows all the partition code to
10  *  be grouped in one location, and it to be mostly self
11  *  contained.
12  *
13  *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
14  */
15
16 #include <linux/slab.h>
17 #include <linux/vmalloc.h>
18 #include <linux/ctype.h>
19 #include <linux/genhd.h>
20
21 #include "check.h"
22 #include "mtdpart.h"
23
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"
36 #include "karma.h"
37 #include "sysv68.h"
38
39 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
40
41 static int (*check_part[])(struct parsed_partitions *) = {
42         /*
43          * Probe partition formats with tables at disk address 0
44          * that also have an ADFS boot block at 0xdc0.
45          */
46 #ifdef CONFIG_ACORN_PARTITION_ICS
47         adfspart_check_ICS,
48 #endif
49 #ifdef CONFIG_ACORN_PARTITION_POWERTEC
50         adfspart_check_POWERTEC,
51 #endif
52 #ifdef CONFIG_ACORN_PARTITION_EESOX
53         adfspart_check_EESOX,
54 #endif
55
56         /*
57          * Now move on to formats that only have partition info at
58          * disk address 0xdc0.  Since these may also have stale
59          * PC/BIOS partition tables, they need to come before
60          * the msdos entry.
61          */
62 #ifdef CONFIG_ACORN_PARTITION_CUMANA
63         adfspart_check_CUMANA,
64 #endif
65 #ifdef CONFIG_ACORN_PARTITION_ADFS
66         adfspart_check_ADFS,
67 #endif
68
69 #ifdef CONFIG_EFI_PARTITION
70         efi_partition,          /* this must come before msdos */
71 #endif
72 #ifdef CONFIG_SGI_PARTITION
73         sgi_partition,
74 #endif
75 #ifdef CONFIG_LDM_PARTITION
76         ldm_partition,          /* this must come before msdos */
77 #endif
78 #ifdef CONFIG_MSDOS_PARTITION
79         msdos_partition,
80 #endif
81 #ifdef CONFIG_OSF_PARTITION
82         osf_partition,
83 #endif
84 #ifdef CONFIG_SUN_PARTITION
85         sun_partition,
86 #endif
87 #ifdef CONFIG_AMIGA_PARTITION
88         amiga_partition,
89 #endif
90 #ifdef CONFIG_ATARI_PARTITION
91         atari_partition,
92 #endif
93 #ifdef CONFIG_MAC_PARTITION
94         mac_partition,
95 #endif
96 #ifdef CONFIG_ULTRIX_PARTITION
97         ultrix_partition,
98 #endif
99 #ifdef CONFIG_IBM_PARTITION
100         ibm_partition,
101 #endif
102 #ifdef CONFIG_KARMA_PARTITION
103         karma_partition,
104 #endif
105 #ifdef CONFIG_SYSV68_PARTITION
106         sysv68_partition,
107 #endif
108
109 #if CONFIG_MMC_DW_ROCKCHIP
110     mtdpart_partition,
111 #endif
112
113         NULL
114 };
115
116 static struct parsed_partitions *allocate_partitions(struct gendisk *hd)
117 {
118         struct parsed_partitions *state;
119         int nr;
120
121         state = kzalloc(sizeof(*state), GFP_KERNEL);
122         if (!state)
123                 return NULL;
124
125         nr = disk_max_parts(hd);
126         state->parts = vzalloc(nr * sizeof(state->parts[0]));
127         if (!state->parts) {
128                 kfree(state);
129                 return NULL;
130         }
131
132         state->limit = nr;
133
134         return state;
135 }
136
137 void free_partitions(struct parsed_partitions *state)
138 {
139         vfree(state->parts);
140         kfree(state);
141 }
142
143 struct parsed_partitions *
144 check_partition(struct gendisk *hd, struct block_device *bdev)
145 {
146         struct parsed_partitions *state;
147         int i, res, err;
148
149         state = allocate_partitions(hd);
150         if (!state)
151                 return NULL;
152         state->pp_buf = (char *)__get_free_page(GFP_KERNEL);
153         if (!state->pp_buf) {
154                 free_partitions(state);
155                 return NULL;
156         }
157         state->pp_buf[0] = '\0';
158
159         state->bdev = bdev;
160         disk_name(hd, 0, state->name);
161         snprintf(state->pp_buf, PAGE_SIZE, " %s:", state->name);
162         if (isdigit(state->name[strlen(state->name)-1]))
163                 sprintf(state->name, "p");
164
165         i = res = err = 0;
166         while (!res && check_part[i]) {
167                 memset(state->parts, 0, state->limit * sizeof(state->parts[0]));
168                 res = check_part[i++](state);
169                 if (res < 0) {
170                         /* We have hit an I/O error which we don't report now.
171                         * But record it, and let the others do their job.
172                         */
173                         err = res;
174                         res = 0;
175                 }
176
177         }
178         if (res > 0) {
179                 printk(KERN_INFO "%s", state->pp_buf);
180
181                 free_page((unsigned long)state->pp_buf);
182                 return state;
183         }
184         if (state->access_beyond_eod)
185                 err = -ENOSPC;
186         if (err)
187         /* The partition is unrecognized. So report I/O errors if there were any */
188                 res = err;
189         if (!res)
190                 strlcat(state->pp_buf, " unknown partition table\n", PAGE_SIZE);
191         else if (warn_no_part)
192                 strlcat(state->pp_buf, " unable to read partition table\n", PAGE_SIZE);
193
194         printk(KERN_INFO "%s", state->pp_buf);
195
196         free_page((unsigned long)state->pp_buf);
197         free_partitions(state);
198         return ERR_PTR(res);
199 }