partitons: add framework
so we can support multiple format use filetpye to detect the parser to use Cc: Rob Herring <rob.herring@calxeda.com> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
a7d9ec0498
commit
263bb23ed2
|
@ -478,19 +478,7 @@ config PARTITION
|
|||
bool
|
||||
prompt "Enable Partitions"
|
||||
|
||||
config PARTITION_DISK
|
||||
depends on PARTITION
|
||||
bool "DISK partition support"
|
||||
help
|
||||
Add support for handling common partition tables on all kind of disk
|
||||
like devices (harddisks, CF cards, SD cards and so on)
|
||||
|
||||
config PARTITION_DISK_DOS
|
||||
depends on PARTITION_DISK
|
||||
default y
|
||||
bool "DOS partition support"
|
||||
help
|
||||
Add support to handle partitions in DOS style.
|
||||
source common/partitions/Kconfig
|
||||
|
||||
config DEFAULT_ENVIRONMENT
|
||||
bool
|
||||
|
|
|
@ -7,7 +7,7 @@ obj-$(CONFIG_ENV_HANDLING) += environment.o
|
|||
obj-$(CONFIG_AUTO_COMPLETE) += complete.o
|
||||
obj-$(CONFIG_POLLER) += poller.o
|
||||
obj-$(CONFIG_BLOCK) += block.o
|
||||
obj-$(CONFIG_PARTITION_DISK) += partitions.o
|
||||
obj-$(CONFIG_PARTITION_DISK) += partitions.o partitions/
|
||||
|
||||
obj-$(CONFIG_CMD_LOADS) += s_record.o
|
||||
obj-$(CONFIG_OFTREE) += oftree.o
|
||||
|
|
|
@ -27,92 +27,12 @@
|
|||
#include <block.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <disks.h>
|
||||
#include <dma.h>
|
||||
#include <filetype.h>
|
||||
#include <dma.h>
|
||||
|
||||
struct partition {
|
||||
uint64_t first_sec;
|
||||
uint64_t size;
|
||||
};
|
||||
#include "partitions/parser.h"
|
||||
|
||||
struct partition_desc {
|
||||
int used_entries;
|
||||
struct partition parts[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* Guess the size of the disk, based on the partition table entries
|
||||
* @param dev device to create partitions for
|
||||
* @param table partition table
|
||||
* @return sector count
|
||||
*/
|
||||
static int disk_guess_size(struct device_d *dev, struct partition_entry *table)
|
||||
{
|
||||
uint64_t size = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (table[i].partition_start != 0) {
|
||||
size += get_unaligned_le32(&table[i].partition_start) - size;
|
||||
size += get_unaligned_le32(&table[i].partition_size);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a DOS like partition describes this block device
|
||||
* @param blk Block device to register to
|
||||
* @param pd Where to store the partition information
|
||||
*
|
||||
* It seems at least on ARM this routine canot use temp. stack space for the
|
||||
* sector. So, keep the malloc/free.
|
||||
*/
|
||||
static void __maybe_unused try_dos_partition(struct block_device *blk,
|
||||
struct partition_desc *pd)
|
||||
{
|
||||
uint8_t *buffer;
|
||||
struct partition_entry *table;
|
||||
struct partition pentry;
|
||||
int i, rc;
|
||||
|
||||
buffer = dma_alloc(SECTOR_SIZE);
|
||||
|
||||
/* read in the MBR to get the partition table */
|
||||
rc = blk->ops->read(blk, buffer, 0, 1);
|
||||
if (rc != 0) {
|
||||
dev_err(blk->dev, "Cannot read MBR/partition table\n");
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if (is_fat_or_mbr(buffer, NULL) != filetype_mbr) {
|
||||
dev_info(blk->dev, "No partition table found\n");
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
table = (struct partition_entry *)&buffer[446];
|
||||
|
||||
/* valid for x86 BIOS based disks only */
|
||||
if (IS_ENABLED(CONFIG_DISK_BIOS) && blk->num_blocks == 0)
|
||||
blk->num_blocks = disk_guess_size(blk->dev, table);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
pentry.first_sec = get_unaligned_le32(&table[i].partition_start);
|
||||
pentry.size = get_unaligned_le32(&table[i].partition_size);
|
||||
|
||||
if (pentry.first_sec != 0) {
|
||||
pd->parts[pd->used_entries].first_sec = pentry.first_sec;
|
||||
pd->parts[pd->used_entries].size = pentry.size;
|
||||
pd->used_entries++;
|
||||
} else {
|
||||
dev_dbg(blk->dev, "Skipping empty partition %d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
on_error:
|
||||
dma_free(buffer);
|
||||
}
|
||||
static LIST_HEAD(partition_parser_list);
|
||||
|
||||
/**
|
||||
* Register one partition on the given block device
|
||||
|
@ -135,6 +55,33 @@ static int register_one_partition(struct block_device *blk,
|
|||
0, partition_name);
|
||||
}
|
||||
|
||||
static struct partition_parser *partition_parser_get_by_filetype(uint8_t *buf)
|
||||
{
|
||||
enum filetype type;
|
||||
struct partition_parser *parser;
|
||||
|
||||
/* first new partition table as EFI GPT */
|
||||
type = file_detect_type(buf, SECTOR_SIZE * 2);
|
||||
|
||||
list_for_each_entry(parser, &partition_parser_list, list) {
|
||||
if (parser->type == type)
|
||||
return parser;
|
||||
}
|
||||
|
||||
/* if not parser found search for old one
|
||||
* so if EFI GPT not enable take it as MBR
|
||||
* useful for compatibility
|
||||
*/
|
||||
type = file_detect_type(buf, SECTOR_SIZE);
|
||||
|
||||
list_for_each_entry(parser, &partition_parser_list, list) {
|
||||
if (parser->type == type)
|
||||
return parser;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to collect partition information on the given block device
|
||||
* @param blk Block device to examine
|
||||
|
@ -147,10 +94,23 @@ int parse_partition_table(struct block_device *blk)
|
|||
struct partition_desc pdesc = { .used_entries = 0, };
|
||||
int i;
|
||||
int rc = 0;
|
||||
struct partition_parser *parser;
|
||||
uint8_t *buf;
|
||||
|
||||
buf = dma_alloc(SECTOR_SIZE * 2);
|
||||
|
||||
rc = blk->ops->read(blk, buf, 0, 2);
|
||||
if (rc != 0) {
|
||||
dev_err(blk->dev, "Cannot read MBR/partition table\n");
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
parser = partition_parser_get_by_filetype(buf);
|
||||
if (!parser)
|
||||
goto on_error;
|
||||
|
||||
parser->parse(buf, blk, &pdesc);
|
||||
|
||||
#ifdef CONFIG_PARTITION_DISK_DOS
|
||||
try_dos_partition(blk, &pdesc);
|
||||
#endif
|
||||
if (!pdesc.used_entries)
|
||||
return 0;
|
||||
|
||||
|
@ -165,5 +125,14 @@ int parse_partition_table(struct block_device *blk)
|
|||
rc = 0;
|
||||
}
|
||||
|
||||
on_error:
|
||||
dma_free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int partition_parser_register(struct partition_parser *p)
|
||||
{
|
||||
list_add_tail(&p->list, &partition_parser_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
config PARTITION_DISK
|
||||
depends on PARTITION
|
||||
bool "DISK partition support"
|
||||
help
|
||||
Add support for handling common partition tables on all kind of disk
|
||||
like devices (harddisks, CF cards, SD cards and so on)
|
||||
|
||||
config PARTITION_DISK_DOS
|
||||
depends on PARTITION_DISK
|
||||
default y
|
||||
bool "DOS partition support"
|
||||
help
|
||||
Add support to handle partitions in DOS style.
|
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_PARTITION_DISK_DOS) += dos.o
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (C) 2009...2011 Juergen Beisert, Pengutronix
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <disks.h>
|
||||
#include <init.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
/**
|
||||
* Guess the size of the disk, based on the partition table entries
|
||||
* @param dev device to create partitions for
|
||||
* @param table partition table
|
||||
* @return sector count
|
||||
*/
|
||||
static int disk_guess_size(struct device_d *dev, struct partition_entry *table)
|
||||
{
|
||||
uint64_t size = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (table[i].partition_start != 0) {
|
||||
size += get_unaligned_le32(&table[i].partition_start) - size;
|
||||
size += get_unaligned_le32(&table[i].partition_size);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a DOS like partition describes this block device
|
||||
* @param blk Block device to register to
|
||||
* @param pd Where to store the partition information
|
||||
*
|
||||
* It seems at least on ARM this routine canot use temp. stack space for the
|
||||
* sector. So, keep the malloc/free.
|
||||
*/
|
||||
static void dos_partition(void *buf, struct block_device *blk,
|
||||
struct partition_desc *pd)
|
||||
{
|
||||
struct partition_entry *table;
|
||||
struct partition pentry;
|
||||
uint8_t *buffer = buf;
|
||||
int i;
|
||||
|
||||
table = (struct partition_entry *)&buffer[446];
|
||||
|
||||
/* valid for x86 BIOS based disks only */
|
||||
if (IS_ENABLED(CONFIG_DISK_BIOS) && blk->num_blocks == 0)
|
||||
blk->num_blocks = disk_guess_size(blk->dev, table);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
pentry.first_sec = get_unaligned_le32(&table[i].partition_start);
|
||||
pentry.size = get_unaligned_le32(&table[i].partition_size);
|
||||
|
||||
if (pentry.first_sec != 0) {
|
||||
pd->parts[pd->used_entries].first_sec = pentry.first_sec;
|
||||
pd->parts[pd->used_entries].size = pentry.size;
|
||||
pd->used_entries++;
|
||||
} else {
|
||||
dev_dbg(blk->dev, "Skipping empty partition %d\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct partition_parser dos = {
|
||||
.parse = dos_partition,
|
||||
.type = filetype_mbr,
|
||||
};
|
||||
|
||||
static int dos_partition_init(void)
|
||||
{
|
||||
return partition_parser_register(&dos);
|
||||
}
|
||||
postconsole_initcall(dos_partition_init);
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
|
||||
*
|
||||
* Under GPLv2 only
|
||||
*/
|
||||
|
||||
#ifndef __PARTITIONS_PARSER_H__
|
||||
#define __PARTITIONS_PARSER_H__
|
||||
|
||||
#include <block.h>
|
||||
#include <filetype.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#define MAX_PARTITION 8
|
||||
|
||||
struct partition {
|
||||
uint64_t first_sec;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
struct partition_desc {
|
||||
int used_entries;
|
||||
struct partition parts[MAX_PARTITION];
|
||||
};
|
||||
|
||||
struct partition_parser {
|
||||
void (*parse)(void *buf, struct block_device *blk, struct partition_desc *pd);
|
||||
enum filetype type;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
int partition_parser_register(struct partition_parser *p);
|
||||
|
||||
#endif /* __PARTITIONS_PARSER_H__ */
|
Loading…
Reference in New Issue