common: fix mbr filetype detection
Sometimes mbr is erroneously recocognised as FAT partion. Due to this the mbr partition parser is not being called and the partitions on the media are not detected. This patch should fix the problem. The checking is done as in the linux kernel. I have seen the problem using usb sticks. Although partitioning and formatting them under linux. The file system type field in the mbr remains there which causes the wrong detections as FAT32 type and not as mbr. Signed-off-by: Zahari Doychev <zahari.doychev@linux.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
c0d6aa097d
commit
f95ce0fff0
|
@ -24,6 +24,7 @@
|
|||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <envfs.h>
|
||||
#include <disks.h>
|
||||
|
||||
struct filetype_str {
|
||||
const char *name; /* human readable filetype */
|
||||
|
@ -87,6 +88,10 @@ const char *file_type_to_short_string(enum filetype f)
|
|||
#define MBR_PART_start_sect 8
|
||||
#define MBR_OSTYPE_EFI_GPT 0xee
|
||||
|
||||
#define FAT_BS_reserved 14
|
||||
#define FAT_BS_fats 16
|
||||
#define FAT_BS_media 21
|
||||
|
||||
static inline int pmbr_part_valid(const uint8_t *buf)
|
||||
{
|
||||
if (buf[MBR_PART_sys_ind] == MBR_OSTYPE_EFI_GPT &&
|
||||
|
@ -126,6 +131,49 @@ static int is_gpt_valid(const uint8_t *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int fat_valid_media(u8 media)
|
||||
{
|
||||
return (0xf8 <= media || media == 0xf0);
|
||||
}
|
||||
|
||||
static int is_fat_with_no_mbr(const unsigned char *sect)
|
||||
{
|
||||
if (!get_unaligned_le16(§[FAT_BS_reserved]))
|
||||
return 0;
|
||||
|
||||
if (!sect[FAT_BS_fats])
|
||||
return 0;
|
||||
|
||||
if (!fat_valid_media(sect[FAT_BS_media]))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_fat_boot_sector(const void *sect)
|
||||
{
|
||||
struct partition_entry *p;
|
||||
int slot;
|
||||
|
||||
p = (struct partition_entry *) (sect + MBR_Table);
|
||||
/* max 4 partitions */
|
||||
for (slot = 1; slot <= 4; slot++, p++) {
|
||||
if (p->boot_indicator && p->boot_indicator != 0x80) {
|
||||
/*
|
||||
* Even without a valid boot inidicator value
|
||||
* its still possible this is valid FAT filesystem
|
||||
* without a partition table.
|
||||
*/
|
||||
if (slot == 1 && is_fat_with_no_mbr(sect))
|
||||
return 1;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum filetype is_fat_or_mbr(const unsigned char *sector, unsigned long *bootsec)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -107,6 +107,8 @@ static struct partition_parser *partition_parser_get_by_filetype(uint8_t *buf)
|
|||
* useful for compatibility
|
||||
*/
|
||||
type = file_detect_partition_table(buf, SECTOR_SIZE);
|
||||
if (type == filetype_fat && !is_fat_boot_sector(buf))
|
||||
type = filetype_mbr;
|
||||
|
||||
list_for_each_entry(parser, &partition_parser_list, list) {
|
||||
if (parser->type == type)
|
||||
|
|
|
@ -44,6 +44,7 @@ enum filetype file_detect_partition_table(const void *_buf, size_t bufsize);
|
|||
enum filetype file_detect_type(const void *_buf, size_t bufsize);
|
||||
enum filetype file_name_detect_type(const char *filename);
|
||||
enum filetype is_fat_or_mbr(const unsigned char *sector, unsigned long *bootsec);
|
||||
int is_fat_boot_sector(const void *_buf);
|
||||
|
||||
#define ARM_HEAD_SIZE 0x30
|
||||
#define ARM_HEAD_MAGICWORD_OFFSET 0x20
|
||||
|
|
Loading…
Reference in New Issue