From: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
To: kexec@lists.infradead.org
Subject: [PATCH v2 04/14] Verify and read VMCORE(s) in sadump-related formats
Date: Fri, 28 Oct 2011 18:48:26 +0900 [thread overview]
Message-ID: <20111028094826.20940.62887.stgit@localhost6.localdomain6> (raw)
In-Reply-To: <20111028094454.20940.1209.stgit@localhost6.localdomain6>
Try to read VMCORE(s) as sadump-related formats: single partition,
diskset or media backup and verify their header information. If the
VMCORE(s) doesn't belong to each of them, the check continues to
checking of ELF format.
Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
---
makedumpfile.c | 17 +-
sadump_info.c | 480 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sadump_info.h | 10 +
3 files changed, 500 insertions(+), 7 deletions(-)
diff --git a/makedumpfile.c b/makedumpfile.c
index 8a3a3d3..7057009 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -628,11 +628,16 @@ open_dump_memory(void)
if (status == TRUE) {
info->flag_refiltering = TRUE;
return get_kdump_compressed_header_info(info->name_memory);
- } else if (status == FALSE) {
- return TRUE;
- } else {
- return FALSE;
}
+
+ status = check_and_get_sadump_header_info(info->name_memory);
+ if (status == TRUE)
+ return TRUE;
+
+ if (status == ERROR)
+ return TRUE;
+
+ return FALSE;
}
int
@@ -3007,7 +3012,7 @@ dump_dmesg()
if (!open_files_for_creating_dumpfile())
return FALSE;
- if (!info->flag_refiltering) {
+ if (!info->flag_refiltering && !info->flag_sadump) {
if (!get_elf_info(info->fd_memory, info->name_memory))
return FALSE;
}
@@ -5757,7 +5762,7 @@ create_dumpfile(void)
if (!open_files_for_creating_dumpfile())
return FALSE;
- if (!info->flag_refiltering) {
+ if (!info->flag_refiltering && !info->flag_sadump) {
if (!get_elf_info(info->fd_memory, info->name_memory))
return FALSE;
}
diff --git a/sadump_info.c b/sadump_info.c
index c94d233..2f66148 100644
--- a/sadump_info.c
+++ b/sadump_info.c
@@ -20,6 +20,7 @@
#include "makedumpfile.h"
#include "print_info.h"
+#include "sadump_mod.h"
struct sadump_diskset_info {
char *name_memory;
@@ -40,10 +41,470 @@ struct sadump_info {
unsigned long data_offset;
};
+static char *guid_to_str(efi_guid_t *guid, char *buf, size_t buflen);
+static struct tm *efi_time_t_to_tm(const efi_time_t *e);
+static int verify_magic_number(uint32_t magicnum[DUMP_PART_HEADER_MAGICNUM_SIZE]);
+static int read_device(void *buf, size_t bytes, ulong *offset);
+static int read_device_diskset(struct sadump_diskset_info *sdi, void *buf,
+ size_t bytes, ulong *offset);
+static int read_sadump_header(char *filename);
+static int read_sadump_header_diskset(int diskid, struct sadump_diskset_info *sdi);
+
static struct sadump_info sadump_info = {};
static struct sadump_info *si = &sadump_info;
int
+check_and_get_sadump_header_info(char *filename)
+{
+ int i;
+
+ if (!read_sadump_header(filename))
+ return FALSE;
+
+ if (info->flag_sadump_diskset && info->flag_sadump == SADUMP_DISKSET) {
+
+ si->diskset_info[0].fd_memory = info->fd_memory;
+ si->diskset_info[0].sph_memory = si->sph_memory;
+ si->diskset_info[0].data_offset = si->data_offset;
+
+ for (i = 1; i < si->num_disks; ++i) {
+ struct sadump_diskset_info *sdi =
+ &si->diskset_info[i];
+
+ if ((sdi->fd_memory =
+ open(sdi->name_memory, O_RDONLY)) < 0) {
+ ERRMSG("Can't open the dump diskset "
+ "memory(%s). %s\n", sdi->name_memory,
+ strerror(errno));
+ return FALSE;
+ }
+
+ if (!read_sadump_header_diskset(i, sdi))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static char *
+guid_to_str(efi_guid_t *guid, char *buf, size_t buflen)
+{
+ snprintf(buf, buflen,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ guid->data1, guid->data2, guid->data3,
+ guid->data4[0], guid->data4[1], guid->data4[2],
+ guid->data4[3], guid->data4[4], guid->data4[5],
+ guid->data4[6], guid->data4[7]);
+
+ return buf;
+}
+
+static struct tm *
+efi_time_t_to_tm(const efi_time_t *e)
+{
+ static struct tm t;
+ time_t ti;
+
+ memset(&t, 0, sizeof(t));
+
+ t.tm_sec = e->second;
+ t.tm_min = e->minute;
+ t.tm_hour = e->hour;
+ t.tm_mday = e->day;
+ t.tm_mon = e->month - 1;
+ t.tm_year = e->year - 1900;
+
+ if (e->timezone != EFI_UNSPECIFIED_TIMEZONE)
+ t.tm_hour += e->timezone;
+
+ else
+ DEBUG_MSG("sadump: timezone information is missing\n");
+
+ ti = mktime(&t);
+ if (ti == (time_t)-1)
+ return &t;
+
+ return localtime_r(&ti, &t);
+}
+
+static int
+verify_magic_number(uint32_t magicnum[DUMP_PART_HEADER_MAGICNUM_SIZE])
+{
+ int i;
+
+ for (i = 1; i < DUMP_PART_HEADER_MAGICNUM_SIZE; ++i)
+ if (magicnum[i] != (magicnum[i - 1] + 7) * 11)
+ return FALSE;
+
+ return TRUE;
+}
+
+static int
+read_device(void *buf, size_t bytes, ulong *offset)
+{
+ if (lseek(info->fd_memory, *offset, SEEK_SET) < 0) {
+ ERRMSG("Can't seek a file(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (read(info->fd_memory, buf, bytes) != bytes) {
+ ERRMSG("Can't read a file(%s). %s\n",
+ info->name_memory, strerror(errno));
+ return FALSE;
+ }
+ *offset += bytes;
+ return TRUE;
+}
+
+static int
+read_device_diskset(struct sadump_diskset_info *sdi, void *buf,
+ size_t bytes, unsigned long *offset)
+{
+ if (lseek(sdi->fd_memory, *offset, SEEK_SET) < 0) {
+ ERRMSG("Can't seek a file(%s). %s\n",
+ sdi->name_memory, strerror(errno));
+ return FALSE;
+ }
+ if (read(sdi->fd_memory, buf, bytes) != bytes) {
+ ERRMSG("Can't read a file(%s). %s\n",
+ sdi->name_memory, strerror(errno));
+ return FALSE;
+ }
+ *offset += bytes;
+ return TRUE;
+}
+
+static int
+read_sadump_header(char *filename)
+{
+ struct sadump_part_header *sph = NULL;
+ struct sadump_header *sh = NULL;
+ struct sadump_disk_set_header *sdh = NULL;
+ struct sadump_media_header *smh = NULL;
+ unsigned long offset = 0, sub_hdr_offset;
+ unsigned long block_size = SADUMP_DEFAULT_BLOCK_SIZE;
+ unsigned long bitmap_len, dumpable_bitmap_len;
+ enum sadump_format_type flag_sadump;
+ uint32_t smram_cpu_state_size = 0;
+ char guid[33];
+
+ if ((si->sph_memory = malloc(SADUMP_DEFAULT_BLOCK_SIZE)) == NULL) {
+ ERRMSG("Can't allocate memory for partition header buffer: "
+ "%s\n", strerror(errno));
+ return FALSE;
+ }
+
+ if ((si->sh_memory = malloc(SADUMP_DEFAULT_BLOCK_SIZE)) == NULL) {
+ ERRMSG("Can't allocate memory for dump header buffer: "
+ "%s\n", strerror(errno));
+ return FALSE;
+ }
+
+ if ((si->sdh_memory = malloc(SADUMP_DEFAULT_BLOCK_SIZE)) == NULL) {
+ ERRMSG("Can't allocate memory for disk set header buffer: "
+ "%s\n", strerror(errno));
+ return FALSE;
+ }
+
+ if ((si->smh_memory = malloc(SADUMP_DEFAULT_BLOCK_SIZE)) == NULL) {
+ ERRMSG("Can't allocate memory for media header buffer: "
+ "%s\n", strerror(errno));
+ return FALSE;
+ }
+
+ sph = si->sph_memory;
+ sh = si->sh_memory;
+ sdh = si->sdh_memory;
+ smh = si->smh_memory;
+
+restart:
+ if (block_size < 0)
+ return FALSE;
+
+ if (!read_device(sph, block_size, &offset))
+ return ERROR;
+
+ if (sph->signature1 == SADUMP_SIGNATURE1 &&
+ sph->signature2 == SADUMP_SIGNATURE2) {
+
+ if (sph->set_disk_set == 0) {
+
+ flag_sadump = SADUMP_SINGLE_PARTITION;
+
+ DEBUG_MSG("sadump: read dump device as single partition\n");
+
+ } else {
+
+ flag_sadump = SADUMP_DISKSET;
+
+ DEBUG_MSG("sadump: read dump device as diskset\n");
+
+ }
+
+ } else {
+
+ offset = 0;
+
+ if (!read_device(smh, block_size, &offset))
+ return ERROR;
+
+ if (!read_device(sph, block_size, &offset))
+ return ERROR;
+
+ if (sph->signature1 != SADUMP_SIGNATURE1 ||
+ sph->signature2 != SADUMP_SIGNATURE2) {
+
+ DEBUG_MSG("sadump: does not have partition header\n");
+
+ flag_sadump = SADUMP_UNKNOWN;
+
+ DEBUG_MSG("sadump: read dump device as unknown format\n");
+
+ goto out;
+ }
+
+ flag_sadump = SADUMP_MEDIA_BACKUP;
+
+ DEBUG_MSG("sadump: read dump device as media backup format\n");
+
+ }
+
+ if (!verify_magic_number(sph->magicnum)) {
+ DEBUG_MSG("sadump: invalid magic number\n");
+ return FALSE;
+ }
+
+ if (flag_sadump == SADUMP_DISKSET) {
+ uint32_t header_blocks;
+ size_t header_size;
+
+ if (sph->set_disk_set != 1) {
+ DEBUG_MSG("sadump: id of this disk is %d\n",
+ sph->set_disk_set);
+ return FALSE;
+ }
+
+ if (!read_device(&header_blocks, sizeof(uint32_t),
+ &offset))
+ return FALSE;
+
+ offset -= sizeof(uint32_t);
+ header_size = header_blocks * block_size;
+
+ if (header_size > block_size) {
+ sdh = realloc(sdh, header_size);
+ if (!sdh) {
+ ERRMSG("Can't allocate memory for disk "
+ "set memory\n");
+ return FALSE;
+ }
+ }
+
+ if (!read_device(sdh, header_size, &offset))
+ return ERROR;
+
+ DEBUG_MSG("sadump: the diskset consists of %u disks\n",
+ sdh->disk_num);
+
+ }
+
+ if (!read_device(sh, block_size, &offset))
+ return FALSE;
+
+ sub_hdr_offset = offset;
+
+ if (strncmp(sh->signature, SADUMP_SIGNATURE, 8) != 0) {
+ DEBUG_MSG("sadump: does not have dump header\n");
+ return FALSE;
+ }
+
+ if (flag_sadump == SADUMP_MEDIA_BACKUP) {
+
+ if (memcmp(&sph->sadump_id, &smh->sadump_id,
+ sizeof(efi_guid_t)) != 0) {
+ DEBUG_MSG("sadump: system ID mismatch\n");
+ DEBUG_MSG(" partition header: %s\n",
+ guid_to_str(&sph->sadump_id, guid,
+ sizeof(guid)));
+ DEBUG_MSG(" media header: %s\n",
+ guid_to_str(&smh->sadump_id, guid,
+ sizeof(guid)));
+ return FALSE;
+ }
+
+ if (memcmp(&sph->disk_set_id, &smh->disk_set_id,
+ sizeof(efi_guid_t)) != 0) {
+ DEBUG_MSG("sadump: disk set ID mismtch\n");
+ DEBUG_MSG(" partition header: %s\n",
+ guid_to_str(&sph->disk_set_id, guid,
+ sizeof(guid)));
+ DEBUG_MSG(" media header: %s\n",
+ guid_to_str(&smh->disk_set_id, guid,
+ sizeof(guid)));
+ return FALSE;
+ }
+
+ if (memcmp(&sph->time_stamp, &smh->time_stamp,
+ sizeof(efi_time_t)) != 0) {
+ DEBUG_MSG("sadump: time stamp mismatch\n");
+ DEBUG_MSG(" partition header: %s",
+ asctime(efi_time_t_to_tm(&sph->time_stamp)));
+ DEBUG_MSG(" media header: %s",
+ asctime(efi_time_t_to_tm(&smh->time_stamp)));
+ }
+
+ if (smh->sequential_num != 1) {
+ DEBUG_MSG("sadump: first media file has sequential "
+ "number %d\n", smh->sequential_num);
+ return FALSE;
+ }
+
+ }
+
+ if (sh->block_size != block_size) {
+ block_size = sh->block_size;
+ offset = 0;
+ goto restart;
+ }
+
+ if (sh->sub_hdr_size > 0) {
+ if (!read_device(&smram_cpu_state_size, sizeof(uint32_t),
+ &offset)) {
+ DEBUG_MSG("sadump: cannot read SMRAM CPU STATE size\n");
+ return FALSE;
+ }
+ smram_cpu_state_size /= sh->nr_cpus;
+
+ offset -= sizeof(uint32_t);
+ offset += sh->sub_hdr_size * block_size;
+ }
+
+ if (!sh->bitmap_blocks) {
+ DEBUG_MSG("sadump: bitmap_blocks is zero\n");
+ return FALSE;
+ }
+
+ if (!sh->dumpable_bitmap_blocks) {
+ DEBUG_MSG("sadump: dumpable_bitmap_blocks is zero\n");
+ return FALSE;
+ }
+
+ bitmap_len = block_size * sh->bitmap_blocks;
+ dumpable_bitmap_len = block_size * sh->dumpable_bitmap_blocks;
+
+ si->sub_hdr_offset = sub_hdr_offset;
+ si->smram_cpu_state_size = smram_cpu_state_size;
+ si->data_offset = offset + bitmap_len + dumpable_bitmap_len;
+
+out:
+ switch (flag_sadump) {
+ case SADUMP_SINGLE_PARTITION:
+ DEBUG_MSG("sadump: single partition configuration\n");
+ break;
+ case SADUMP_DISKSET:
+ DEBUG_MSG("sadump: diskset configuration with %d disks\n",
+ sdh->disk_num);
+ break;
+ case SADUMP_MEDIA_BACKUP:
+ DEBUG_MSG("sadump: media backup file\n");
+ break;
+ case SADUMP_UNKNOWN:
+ DEBUG_MSG("sadump: unknown format\n");
+ break;
+ }
+
+ info->flag_sadump = flag_sadump;
+
+ return TRUE;
+}
+
+static int
+read_sadump_header_diskset(int diskid, struct sadump_diskset_info *sdi)
+{
+ struct sadump_part_header *sph = NULL;
+ unsigned long offset = 0;
+ char guid[33];
+
+ if ((sph = malloc(si->sh_memory->block_size)) == NULL) {
+ ERRMSG("Can't allocate memory for partition header buffer. "
+ "%s\n", strerror(errno));
+ goto error;
+ }
+
+ if (!read_device_diskset(sdi, sph, si->sh_memory->block_size,
+ &offset))
+ goto error;
+
+ if (sph->signature1 != SADUMP_SIGNATURE1 ||
+ sph->signature2 != SADUMP_SIGNATURE2) {
+ DEBUG_MSG("sadump: does not have partition header\n");
+ free(sph);
+ goto error;
+ }
+
+ if (memcmp(&si->sph_memory->sadump_id, &sph->sadump_id,
+ sizeof(efi_guid_t)) != 0) {
+ DEBUG_MSG("sadump: system ID mismatch\n");
+ DEBUG_MSG(" partition header on disk #1: %s\n",
+ guid_to_str(&si->sph_memory->sadump_id, guid,
+ sizeof(guid)));
+ DEBUG_MSG(" partition header on disk #%d: %s\n", diskid,
+ guid_to_str(&sph->sadump_id, guid, sizeof(guid)));
+ goto error;
+ }
+
+ if (memcmp(&si->sph_memory->disk_set_id, &sph->disk_set_id,
+ sizeof(efi_guid_t)) != 0) {
+ DEBUG_MSG("sadump: disk set ID mismatch\n");
+ DEBUG_MSG(" partition header on disk #1: %s\n",
+ guid_to_str(&si->sph_memory->disk_set_id, guid,
+ sizeof(guid)));
+ DEBUG_MSG(" partition header on disk #%d: %s\n", diskid,
+ guid_to_str(&sph->disk_set_id, guid, sizeof(guid)));
+ goto error;
+ }
+
+ if (memcmp(&si->sdh_memory->vol_info[diskid-1].id, &sph->vol_id,
+ sizeof(efi_guid_t)) != 0) {
+ DEBUG_MSG("sadump: volume ID mismatch\n");
+ DEBUG_MSG(" disk set header on disk #1: %s\n",
+ guid_to_str(&si->sdh_memory->vol_info[diskid-1].id,
+ guid, sizeof(guid)));
+ DEBUG_MSG(" partition header on disk #%d: %s\n",
+ diskid+1,
+ guid_to_str(&sph->vol_id, guid, sizeof(guid)));
+ goto error;
+ }
+
+ if (memcmp(&si->sph_memory->time_stamp, &sph->time_stamp,
+ sizeof(efi_time_t)) != 0) {
+ DEBUG_MSG("sadump time stamp mismatch\n");
+ DEBUG_MSG(" partition header on disk #1: %s\n",
+ asctime(efi_time_t_to_tm
+ (&si->sph_memory->time_stamp)));
+ DEBUG_MSG(" partition header on disk #%d: %s\n",
+ diskid, asctime(efi_time_t_to_tm(&sph->time_stamp)));
+ }
+
+ if (diskid+1 != sph->set_disk_set) {
+ DEBUG_MSG("sadump: wrong disk order; #%d expected but #%d given\n",
+ diskid+1, sph->set_disk_set);
+ goto error;
+ }
+
+ sdi->sph_memory = sph;
+ sdi->data_offset = si->sh_memory->block_size;
+
+ return TRUE;
+
+error:
+ free(sph);
+
+ return FALSE;
+}
+
+int
sadump_add_diskset_info(char *name_memory)
{
si->num_disks++;
@@ -71,8 +532,25 @@ sadump_head_disk_name_memory(void)
void
free_sadump_info(void)
{
- if (si->diskset_info)
+ if (si->sph_memory)
+ free(si->sph_memory);
+ if (si->sh_memory)
+ free(si->sh_memory);
+ if (si->sdh_memory)
+ free(si->sdh_memory);
+ if (si->smh_memory)
+ free(si->smh_memory);
+ if (si->diskset_info) {
+ int i;
+
+ for (i = 1; i < si->num_disks; ++i) {
+ if (si->diskset_info[i].fd_memory)
+ close(si->diskset_info[i].fd_memory);
+ if (si->diskset_info[i].sph_memory)
+ free(si->diskset_info[i].sph_memory);
+ }
free(si->diskset_info);
+ }
}
#endif /* defined(__x86__) && defined(__x86_64__) */
diff --git a/sadump_info.h b/sadump_info.h
index 863956d..c54d29f 100644
--- a/sadump_info.h
+++ b/sadump_info.h
@@ -24,6 +24,7 @@
#if defined(__x86__) || defined(__x86_64__)
+int check_and_get_sadump_header_info(char *filename);
int sadump_add_diskset_info(char *name_memory);
char *sadump_head_disk_name_memory(void);
void free_sadump_info(void);
@@ -35,6 +36,15 @@ static inline int sadump_is_supported_arch(void)
#else
+static inline int check_and_get_sadump_header_info(char *filename)
+{
+ info->flag_sadump = SADUMP_UNKNOWN;
+
+ DEBUG_MSG("sadump: unsupported architecture\n");
+
+ return TRUE;
+}
+
static inline int sadump_add_diskset_info(char *name_memory)
{
return TRUE;
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
next prev parent reply other threads:[~2011-10-28 9:48 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-28 9:48 [PATCH v2 00/14] Support Fujitsu Stand Alone Dump Format HATAYAMA Daisuke
2011-10-28 9:48 ` [PATCH v2 01/14] Add sadump module header file HATAYAMA Daisuke
2011-10-28 9:48 ` [PATCH v2 02/14] Extend DumpInfo structure HATAYAMA Daisuke
2011-10-28 9:48 ` [PATCH v2 03/14] Implement command-line processing HATAYAMA Daisuke
2011-10-28 9:48 ` HATAYAMA Daisuke [this message]
2011-10-28 9:48 ` [PATCH v2 05/14] Export helpers for bitmap table handling HATAYAMA Daisuke
2011-10-28 9:48 ` [PATCH v2 06/14] Initialize internal data according to sadump-related formats HATAYAMA Daisuke
2011-10-28 9:48 ` [PATCH v2 07/14] Initialize debug information for ELF note extraction HATAYAMA Daisuke
2011-10-28 9:48 ` [PATCH v2 08/14] Implement readmem() interface on sadump-related formats HATAYAMA Daisuke
2011-10-28 9:48 ` [PATCH v2 09/14] Estimate phys_base based on linux_banner position HATAYAMA Daisuke
2011-10-28 9:48 ` [PATCH v2 10/14] Generate and save VMCOREINFO and ELF note information HATAYAMA Daisuke
2011-12-20 8:18 ` Atsushi Kumagai
2011-12-20 9:31 ` HATAYAMA Daisuke
2011-12-21 8:22 ` Atsushi Kumagai
2011-12-21 8:39 ` HATAYAMA Daisuke
2011-10-28 9:49 ` [PATCH v2 11/14] Procees CPUs based on online ones HATAYAMA Daisuke
2011-10-28 9:49 ` [PATCH v2 12/14] Read kexec backup region HATAYAMA Daisuke
2011-10-28 9:49 ` [PATCH v2 13/14] Add description of sadump-related formts in usage information HATAYAMA Daisuke
2011-10-28 9:49 ` [PATCH v2 14/14] Add description of sadump-related formats in manual page HATAYAMA Daisuke
2011-10-28 12:05 ` [PATCH v2 00/14] Support Fujitsu Stand Alone Dump Format tachibana
2011-12-15 6:47 ` HATAYAMA Daisuke
2011-12-15 8:55 ` tachibana
2011-12-15 9:09 ` HATAYAMA Daisuke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20111028094826.20940.62887.stgit@localhost6.localdomain6 \
--to=d.hatayama@jp.fujitsu.com \
--cc=kexec@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.