From: kaku <fk...@us...> - 2006-03-03 00:00:07
|
Update of /cvsroot/mkdump/utils/mkd_conv In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15375 Added Files: mkd_conv.c mkd_conv.h mkd_conv_lkcd_i386.c mkd_conv_lkcd_x86_64.c Log Message: Added mkd_conv utility. --- NEW FILE: mkd_conv.h --- /* * mkd_conv/mkd_conv.h * * $Id: mkd_conv.h,v 1.1 2006/03/03 00:00:01 fkak Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _MKDC_MKD_CONV_H_ #define _MKDC_MKD_CONV_H_ #include "typedefs.h" #include "./lkcd_dump.h" struct mkd_conv_opts { int f_conv; int f_chk; int f_info; int f_format; int f_direct; int f_force; int f_noverbose; int f_save; int f_writeu; }; typedef struct mkd_conv_opts mkd_conv_opts_t; struct dump_cache { int arch; u32 p_sz; int p_num; size_t buf_sz; u64 blk; int r_dv; int r_dm; int r_dt; struct dump_version *dvp; struct mem_seg *dmp; struct dump_version *dtp; char *buf; }; typedef struct dump_cache dump_cache_t; #define DSP_INDICATOR(total, current, old_per) \ do { \ int cur_per; \ cur_per = current * 100 / total; \ if (cur_per > old_per) { \ fprintf(stderr, "\r%d%%", cur_per); \ fflush(stderr); \ old_per = cur_per; \ } \ } while (0) #ifdef _DEBUG_PRINT #define DPRINT(x) printf x; #else #define DPRINT(x) #endif #define CHECK_HEADER_VERBOSE 1 #define CHECK_HEADER_NOVERBOSE 0 #define COPY_DUMP_CHK 1 #define COPY_DUMP_NOCHK 0 extern void fprintf_verb(int verbose, char *msg); extern int check_header(struct dump_version *dvp, int arch, int verbose); extern int check_memseg(struct mem_seg *dmp, u64 *blk, int verbose); extern int check_tailer(struct dump_version *dvp0, struct dump_version *dvp1, int arch, int verbose); extern int mkd2lkcd_i386(int in_fd, int out_fd, dump_cache_t *dcache, u64 *blk_cnt); extern int mkd2lkcd_x86_64(int in_fd, int out_fd, dump_cache_t *dcache, u64 *blk_cnt); #endif /* _MKDC_MKD_CONV_H_ */ --- NEW FILE: mkd_conv.c --- /* * mkd_conv/mkd_conv.c * * $Id: mkd_conv.c,v 1.1 2006/03/03 00:00:00 fkak Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #include <getopt.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/utsname.h> #include <stdlib.h> #include <dirent.h> #include "typedefs.h" #include "minik_dump.h" #include "mkd_conv.h" #define EXIT_OK 0 #define EXIT_ERROR 1 #define DUMP_CACHE_NUM 128 #define PAGE_SHIFT 12 #define PAGE_SIZE (1UL << PAGE_SHIFT) char *program_name; static int get_headers(int fd_in, dump_cache_t *dcache, int verbose); static int update_header(int fd, dump_cache_t *dcache, u32 unique, int verbose); static int copy_dump_no_conv(int fd_in, int fd_out, char *file_nm, dump_cache_t *dcache, int chk, u64 *sum); static int check_dump_stat(int fd, dump_cache_t *dcache, u64 *blk); static int format_ddev(int fd, char *file_nm, dump_cache_t *dcache, u64 *sum); static int check_devf(int fd, char *file_nm, u64 *size); void fprintf_verb(int verbose, char *msg); int check_header(struct dump_version *dvp, int arch, int verbose); int check_memseg(struct mem_seg *dmp, u64 *blk, int verbose); int check_tailer(struct dump_version *dvp0, struct dump_version *dvp1, int arch, int verbose); int main(int argc, char *argv[]) { int ret = EXIT_ERROR, result; int res_conv = 0; int res_header = 0; char *file_in = NULL; char *file_out = NULL; int fd_in = -1, fd_out = -1; int opt; int f_direct_chk = COPY_DUMP_CHK; char *endptr = NULL; int open_flags = O_RDONLY, verbose = CHECK_HEADER_VERBOSE; u32 unique; mkd_conv_opts_t opts_f = { .f_conv = 0, .f_chk = 0, .f_info = 0, .f_format = 0, .f_direct = 0, .f_force = 0, .f_noverbose = 0, .f_save = 0, .f_writeu = 0 }; struct utsname utsname; int arch, arch_uname = 0, arch_in = 0; char *buf = NULL; dump_cache_t dcache = { .arch = 0, .p_sz = PAGE_SIZE, .p_num = DUMP_CACHE_NUM, .buf_sz = 0, .blk = 0, .r_dv = -1, .r_dm = -1, .r_dt = -1, .dvp = NULL, .dmp = NULL, .dtp = NULL, .buf = NULL }; int i; u64 f_sum = 0, blk_cnt = 0; int flg_remove = 1; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); program_name = argv[0]; while ((opt = getopt(argc, argv, "CIPcfnsa:d:w:")) > 0) { switch (opt) { case 'C': opts_f.f_chk = 1; break; case 'I': opts_f.f_info = 1; break; case 'P': opts_f.f_format = 1; open_flags = O_RDWR; break; case 'f': opts_f.f_force = 1; break; case 'n': opts_f.f_noverbose = 1; verbose = CHECK_HEADER_NOVERBOSE; break; case 's': opts_f.f_save = 1; break; case 'a': arch_in = strtoul(optarg, &endptr, 0); if ('\0' != *endptr) { if (errno) { perror("strtoul -a option"); } else { fprintf(stderr, "-a option strtoul error\n"); } goto L_close; } if (arch_in > DUMP_ARCH_IA64 || arch_in < DUMP_ARCH_I386) { fprintf(stderr, "-a invalid architecture.\n"); goto L_close; } break; case 'd': opts_f.f_direct = 1; result = strtoul(optarg, &endptr, 0); if ('\0' != *endptr) { if (errno) { perror("strtoul -d option"); } else { fprintf(stderr, "-d option strtoul error\n"); } goto L_close; } if (result == 0) { f_direct_chk = COPY_DUMP_NOCHK; } else { f_direct_chk = COPY_DUMP_CHK; } break; case 'w': opts_f.f_writeu = 1; open_flags = O_RDWR; unique = strtoul(optarg, &endptr, 0); if ('\0' != *endptr) { if (errno) { perror("strtoul -w option"); } else { fprintf(stderr, "-w option strtoul error\n"); } goto L_close; } break; default: goto L_close; break; } } do { int f_1arg = opts_f.f_chk + opts_f.f_info + opts_f.f_format + opts_f.f_writeu; int f_2arg = opts_f.f_direct + opts_f.f_save; switch(argc - optind) { case 1: if (f_2arg || f_1arg == 0 || opts_f.f_force == 1) { fprintf(stderr, "invalid arguments.\n"); goto L_close; } file_in = argv[optind]; break; case 2: if (f_1arg) { fprintf(stderr, "invalid arguments.\n"); goto L_close; } if (f_2arg == 0) { opts_f.f_conv = 1; } file_in = argv[optind]; file_out = argv[optind+1]; break; default: fprintf(stderr, "invalid arguments.\n"); goto L_close; break; } } while(0); /* get boot architecture */ if (uname(&utsname) < 0) { perror("uname"); goto L_close; } if (strncmp(utsname.machine, "i386", 4) == 0) { arch_uname = DUMP_ARCH_I386; } else if (strncmp(utsname.machine, "i686", 4) == 0) { arch_uname = DUMP_ARCH_I386; } else if (strncmp(utsname.machine, "x86_64", 6) == 0) { arch_uname = DUMP_ARCH_X8664; } else if (strncmp(utsname.machine, "ia64", 4) == 0) { arch_uname = DUMP_ARCH_IA64; } else { fprintf(stderr, "invalid architecture(in uname).\n"); goto L_close; } if (arch_in) { arch = arch_in; } else { arch = arch_uname; } dcache.arch = arch; dcache.buf_sz = dcache.p_sz * dcache.p_num; if ((result = posix_memalign((void *)&(dcache.buf), 512, dcache.buf_sz)) != 0) { /* posix_memalign() is not set errno. */ fprintf(stderr, "posix_memalign(for cache of dump data) : %d", result); goto L_close; } memset(dcache.buf, 0, dcache.buf_sz); // open_flags |= O_DIRECT; fd_in = open(file_in, open_flags); if (fd_in < 0) { perror("open input file"); goto L_close; } if (file_out != NULL) { open_flags = O_WRONLY | O_CREAT | O_EXCL; fd_out = open(file_out, open_flags, 0444); if (fd_out < 0) { perror("open output file"); goto L_close; } } /* format dump device */ if (opts_f.f_format) { if ((result = format_ddev(fd_in, file_in, &dcache, &f_sum)) < 0) { goto L_close; } goto L_normal; } /* copy dump without checking header) */ if (opts_f.f_direct && f_direct_chk == COPY_DUMP_NOCHK) { if ((res_conv = copy_dump_no_conv(fd_in, fd_out, file_in, &dcache, f_direct_chk, &f_sum)) < 0) { goto L_close; } goto L_normal; } /* read dump headers */ if ((result = get_headers(fd_in, &dcache, verbose)) < 0) { goto L_close; } if (dcache.r_dv || dcache.r_dm || dcache.r_dt) { res_header = -1; } /* * for each options */ /* get header information */ if (opts_f.f_info) { printf("%d %d %x\n", dcache.dvp->dv_version, dcache.dvp->dv_arch, dcache.dvp->dv_unique); if (res_header < 0) { goto L_close; } goto L_normal; } /* update dump unique */ if (opts_f.f_writeu) { result = update_header(fd_in, &dcache, unique, verbose); if (result < 0) { goto L_close; } goto L_normal; } /* copy dump with checking header */ if (opts_f.f_direct) { if ((res_conv = copy_dump_no_conv(fd_in, fd_out, file_in, &dcache, f_direct_chk, &f_sum)) < 0) { goto L_close; } goto L_normal; } /* check dump status */ if (opts_f.f_chk) { u64 blk; if (dcache.r_dv || dcache.r_dm) { goto L_close; } result = check_dump_stat(fd_in, &dcache, &blk); printf("%d %d\n", result, blk); if (result == 0) { goto L_normal; } else { goto L_close; } } /* convert mkdump to lkcd */ if (opts_f.f_save && res_header) { if ((res_conv = copy_dump_no_conv(fd_in, fd_out, file_in, &dcache, COPY_DUMP_NOCHK, &f_sum)) < 0) { goto L_close; } } else if (opts_f.f_force == 0 && res_header) { goto L_close; } else { if (dcache.dvp->dv_arch == DUMP_ARCH_I386) { res_conv = mkd2lkcd_i386(fd_in, fd_out, &dcache, &blk_cnt); } else if (dcache.dvp->dv_arch == DUMP_ARCH_X8664) { res_conv = mkd2lkcd_x86_64(fd_in, fd_out, &dcache, &blk_cnt); } else { fprintf_verb(verbose, "invalid architecture(in main)."); goto L_close; } f_sum = blk_cnt * dcache.p_sz; if (res_conv < 0) { goto L_close; } } L_normal: flg_remove = 0; ret = EXIT_OK; L_close: if (f_sum && verbose == CHECK_HEADER_VERBOSE) { printf("%lld blocks + %lld bytes (4096bytes/block)\n", f_sum / dcache.p_sz, f_sum % dcache.p_sz); printf("%lld bytes\n", f_sum); } if (fd_out >= 0) { if (close(fd_out) == 0) { if (flg_remove && opts_f.f_force == 0) { if (unlink(file_out) < 0) { perror("unlink output file"); } } } else { perror("close input file"); } } if (fd_in >= 0) { if (close(fd_in) < 0) { perror("close input file"); } } free(buf); free(dcache.buf); free(dcache.dtp); exit(ret); } /* * fprintf(stderr, ...) with cheking verbose */ void fprintf_verb(int verbose, char *msg) { if (msg == NULL) { fprintf(stderr, "no message.\n"); } else if (verbose == CHECK_HEADER_VERBOSE) { fprintf(stderr, "%s\n", msg); } } /* * check dump header */ int check_header(struct dump_version *dvp, int arch, int verbose) { DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); if (memcmp(dvp->dv_magic, DUMP_MAGIC, DUMP_MAGIC_LEN)) { fprintf_verb(verbose, "invalid dump magic."); return -1; } if (dvp->dv_version != DUMP_VERSION) { fprintf_verb(verbose, "invalid dump version."); return -2; } if (dvp->dv_arch != arch) { fprintf_verb(verbose, "unmatched architecture."); if (dvp->dv_arch == DUMP_ARCH_I386 || dvp->dv_arch == DUMP_ARCH_X8664 || dvp->dv_arch == DUMP_ARCH_IA64) { return -3; } else { fprintf_verb(verbose, "invalid architecture."); return -4; } } if (dvp->dv_unique == 0 || dvp->dv_unique == 0xffffffff) { fprintf_verb(verbose, "invalid dump unique."); return -5; } return 0; } /* * check memory segment header */ int check_memseg(struct mem_seg *dmp, u64 *blk, int verbose) { int i; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *blk = 0; if (dmp->seg_num > MAX_MEM_SEG || memcmp(dmp, DUMP_MAGIC, DUMP_MAGIC_LEN) == 0) { fprintf_verb(verbose, "invalid memseg list."); return -1; } /* get dump pages */ for (i = 0; i < dmp->seg_num; i++) { *blk += dmp->seg_list[i].seg_size; } return 0; } /* * check dump tailer */ int check_tailer(struct dump_version *dvp0, struct dump_version *dvp1, int arch, int verbose) { DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); if (check_header(dvp1, arch, verbose) < 0) { fprintf_verb(verbose, "invalid tailer."); return -1; } if (dvp0->dv_unique != dvp1->dv_unique) { fprintf_verb(verbose, "invalid tailer(unmatched dump unique)."); return -1; } return 0; } /* * get headers */ static int get_headers(int fd_in, dump_cache_t *dcache, int verbose) { int result; /* read dump headers */ if ((result = posix_memalign((void *)&(dcache->dvp), 512, dcache->p_sz * 2)) != 0) { /* posix_memalign() is not set errno. */ fprintf(stderr, "posix_memalign(for cache of dump headers) : %d", result); return -1; } if ((result = read(fd_in, dcache->dvp, dcache->p_sz * 2)) != dcache->p_sz * 2) { if (result < 0) { perror("read headers(in main)"); } else { fprintf(stderr, "header read size error(in main) %d : %d", dcache->p_sz * 2, result); } return -1; } dcache->dmp = (struct mem_seg *)((char *)(dcache->dvp) + dcache->p_sz); /* get header information */ dcache->r_dv = check_header(dcache->dvp, dcache->dvp->dv_arch, verbose); dcache->r_dm = check_memseg(dcache->dmp, &(dcache->blk), verbose); /* read dump tailer */ if (dcache->r_dv == 0 && dcache->r_dm == 0) { if (lseek(fd_in, dcache->blk * dcache->p_sz, SEEK_CUR) < 0) { perror("lseek tailer(in main)"); return -1; } if ((result = posix_memalign((void *)&(dcache->dtp), 512, dcache->p_sz)) != 0) { /* posix_memalign() is not set errno. */ fprintf(stderr, "posix_memalign(for cache of dump tailer) : %d", result); return -1; } if ((result = read(fd_in, dcache->dtp, dcache->p_sz)) != dcache->p_sz) { if (result < 0) { perror("read tailer(in main)"); } else { fprintf(stderr, "tailer read size error(in main) %d : %d", dcache->p_sz, result); } return -1; } dcache->r_dt = check_tailer(dcache->dvp, dcache->dtp, dcache->dvp->dv_arch, verbose); if (lseek(fd_in, dcache->p_sz * 2, SEEK_SET) != dcache->p_sz * 2) { perror("lseek header(in main)"); return -1; } } return 0; } /* * update header */ static int update_header(int fd, dump_cache_t *dcache, u32 unique, int verbose) { ssize_t wsz; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); if (lseek(fd, 0, SEEK_SET) != 0) { perror("lseek(in update_header)"); return -1; } dcache->dvp->dv_unique = unique; if ((wsz = write(fd, dcache->dvp, dcache->p_sz)) != dcache->p_sz) { if (wsz < 0) { perror("write(in update_header)"); } else { fprintf(stderr, "header write size error(in update_header) %d : %d\n", dcache->p_sz, wsz); } return -1; } return 0; } /* * dump copy */ static int copy_dump_no_conv(int fd_in, int fd_out, char *file_nm, dump_cache_t *dcache, int chk, u64 *sum) { ssize_t rsz, wsz; size_t rqsz; int result, i, per = -1; u64 max_blk = 0, f_sz = 0; DPRINT(("Enter %s(%d), chk=%d\n", __FUNCTION__,__LINE__,chk)); *sum = 0; if (chk == COPY_DUMP_CHK) { if (dcache->r_dv == 0 && dcache->r_dm == 0) { max_blk = dcache->blk + 3; f_sz = max_blk * dcache->p_sz; } } if (f_sz == 0) { if ((result = check_devf(fd_in, file_nm, &f_sz)) < 0) { return -1; } } if (lseek(fd_in, 0, SEEK_SET) != 0) { perror("lseek(in copy_dump_no_conv)"); return -1; } if (f_sz && dcache->buf_sz > f_sz) { rqsz = f_sz; } else { rqsz = dcache->buf_sz; } do { if ((rsz = read(fd_in, dcache->buf, rqsz)) < 0) { perror("read dump(in copy_dump_no_conv)"); return -1; } if (rsz) { if ((wsz = write(fd_out, dcache->buf, rsz)) != rsz) { if (wsz < 0) { perror("write(in copy_dump_no_conv)"); } else { fprintf(stderr, "write size error(in copy_dump_no_conv) %d : %d\n", rsz, wsz); } return -1; } } if (rsz != dcache->buf_sz) { *sum += rsz; } else { *sum += dcache->buf_sz; if (f_sz && *sum + dcache->buf_sz > f_sz) { rqsz = f_sz - *sum; } else { rqsz = dcache->buf_sz; } } if (f_sz) { DSP_INDICATOR(f_sz, *sum, per); } if (rsz != dcache->buf_sz) { if (per != -1) { fprintf(stderr, "\n"); } break; } } while (rsz > 0); return 0; } /* * check dump status */ static int check_dump_stat(int fd, dump_cache_t *dcache, u64 *blk) { ssize_t rsz; u64 max_blk; struct dump_version *wdvp = NULL; char *wp; int i, f_end, per = -1; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); /* check header */ *blk = 0; if (dcache->r_dv || dcache->r_dm) { fprintf(stderr, "invalid header(in check_dump_stat).\n"); return -1; } /* check tailer */ max_blk = dcache->blk + 3; /* for dump header, tailer */ if (dcache->r_dt == 0) { *blk = max_blk; return 0; } /* check number of dump pages */ if (lseek(fd, dcache->p_sz * 2, SEEK_SET) != dcache->p_sz * 2) { perror("lseek dump data(in check_dump_stat)"); return -1; } for (*blk = 2, f_end = 0, per = -1; *blk < max_blk;) { int rcnt; if ((rsz = read(fd, dcache->buf, dcache->buf_sz)) < 0) { perror("read dump(in check_dump_stat)"); return -1; } else if (rsz == 0) { break; } rcnt = rsz / dcache->p_sz; wp = dcache->buf; for(i = 0; i < rcnt; i++) { wdvp = (struct dump_version *)wp; if (memcmp(wdvp, DUMP_MAGIC, DUMP_MAGIC_LEN) == 0 && dcache->dvp->dv_unique != wdvp->dv_unique) { f_end = 1; break; } wp += dcache->p_sz; (*blk)++; DSP_INDICATOR(max_blk, *blk, per); } if (rsz != dcache->buf_sz || f_end) { break; } } if (per != -1) { fprintf(stderr, "\n"); } return 1; } /* * format dump device */ static int format_ddev(int fd, char *file_nm, dump_cache_t *dcache, u64 *sum) { ssize_t wsz; u64 blk_cnt = 0, max_blk, f_sz = 0; struct dump_version dh_version; char *wp; int i, result, per = -1; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *sum = 0; strncpy(dh_version.dv_magic, DUMP_MAGIC, DUMP_MAGIC_LEN); dh_version.dv_version = DUMP_VERSION; dh_version.dv_arch = dcache->arch; if ((result = check_devf(fd, file_nm, &f_sz)) < 0) { return -1; } else if (result > 0) { fprintf(stderr, "not device file(in format_ddev).\n"); return -1; } memset(dcache->buf, 0, dcache->buf_sz); wp = dcache->buf; for(i = 0; i < dcache->p_num; i++) { memcpy(wp, &dh_version, sizeof(dh_version)); wp += dcache->p_sz; } blk_cnt = 0; do { wp = dcache->buf; for(i = 0; i < dcache->p_num; i++) { ((struct dump_version *)wp)->dv_unique = blk_cnt; wp += dcache->p_sz; blk_cnt++; } if ((wsz = write(fd, dcache->buf, dcache->buf_sz)) != dcache->buf_sz) { if (wsz < 0) { perror("write(in format_ddev)"); return -1; } *sum += wsz; } else { *sum += dcache->buf_sz; } if (f_sz) { DSP_INDICATOR(f_sz, *sum, per); } if (wsz != dcache->buf_sz) { break; } } while (wsz > 0); if (per != -1) { fprintf(stderr, "\n"); } return 0; } /* * check if device file */ static int check_devf(int fd, char *file_nm, u64 *size) { struct stat stat_buf; FILE *fp; DIR *dp; char *str; char *endptr = NULL; char command[257]; char buf[257]; int lng; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *size = 0; if (fstat(fd, &stat_buf) < 0) { perror("fstat(in format_ddev)"); return -1; } else if (stat_buf.st_rdev == 0) { *size = stat_buf.st_size; return 1; } if ((dp = opendir("/sys")) != NULL) { closedir(dp); if ((str = strrchr(file_nm, '/')) == NULL) { fprintf(stderr, "invalid file name.\n"); return 2; } str++; /* get sysfs file path */ lng = snprintf(command, sizeof(command), "find /sys/block -name %s", str); if (lng > sizeof(command) || lng < 0) { fprintf(stderr, "too long file name.\n"); return -1; } if ((fp = popen(command, "r")) == NULL) { perror("popen(get path"); return 2; } if (fgets(buf, sizeof(buf), fp) == NULL) { pclose(fp); return 2; } if (pclose(fp) < 0) { perror("pclose"); } if ((str = strchr(buf, '\n')) != NULL) { *str = '\0'; } /* get device file size */ lng = snprintf(command, sizeof(command), "cat %s/size", buf); if (lng > sizeof(command) || lng < 0) { fprintf(stderr, "too long file name.\n"); return -1; } if ((fp = popen(command, "r")) == NULL) { perror("popen(get file size"); return 2; } if (fgets(buf, sizeof(buf), fp) == NULL) { pclose(fp); return 2; } if ((str = strchr(buf, '\n')) != NULL) { *str = '\0'; } if (pclose(fp) < 0) { perror("pclose"); } *size = strtoll(buf, &endptr, 0); if ('\0' != *endptr) { fprintf(stderr, "file size error.\n"); *size = 0; return -1; } *size = *size * 512; } return 0; } --- NEW FILE: mkd_conv_lkcd_x86_64.c --- /* * mkd_conv/mkd_conv_lkcd_x86_64.c * * $Id: mkd_conv_lkcd_x86_64.c,v 1.1 2006/03/03 00:00:01 fkak Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include "typedefs.h" #include "kernel_x86_64.h" #include "minik_dump.h" #include "minik_dump_x86_64.h" #include "lkcd_dump_x86_64.h" #include "mkd_conv.h" /* buffers */ static char lkcd_header_buf[64 * 1024]; static MKDC_LKCD_DP_T lkcd_page_header; static int convert_header(struct dump_header_x86_64 *dhp, struct mem_seg *msegp, MKDC_LKCD_DH_T *lkcd_dhp, MKDC_LKCD_DHA_X86_64_T *lkcd_dahp, u64 total_page); int mkd2lkcd_x86_64(int in_fd, int out_fd, dump_cache_t *dcache, u64 *blk_cnt) { char *page_buf; int all_ok = 0; int i, per = -1; struct mem_seg *msegp; u64 pfn, end_pfn, sum; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *blk_cnt = 0; msegp = dcache->dmp; page_buf = dcache->buf; /* * read and check header */ if (check_header(dcache->dvp, DUMP_ARCH_X8664, CHECK_HEADER_NOVERBOSE) < 0) { goto out; } /* * convert header and write lkcd_header */ if (dcache->r_dm) { fprintf(stderr, "invalid memseg.\n"); goto out; } if (dcache->blk == 0) { fprintf(stderr, "no page.\n"); goto out; } sum = dcache->blk; if (convert_header((struct dump_header_x86_64 *)(dcache->dvp), msegp, (MKDC_LKCD_DH_T *)lkcd_header_buf, (MKDC_LKCD_DHA_X86_64_T *)(lkcd_header_buf + sizeof(MKDC_LKCD_DH_T)), dcache->blk) < 0) { goto out; } if (write(out_fd, lkcd_header_buf, sizeof(lkcd_header_buf)) != sizeof(lkcd_header_buf)) { if (errno) { perror("write header"); } else { fprintf(stderr, "header write size error.\n"); } goto out; } /* * write pages */ for (i = 0, *blk_cnt = 0, per = -1; i < msegp->seg_num; i++) { pfn = msegp->seg_list[i].seg_start_pfn; end_pfn = pfn + msegp->seg_list[i].seg_size; for (; pfn < end_pfn; pfn++) { if (read(in_fd, page_buf, PAGE_SIZE_X86_64) != PAGE_SIZE_X86_64) { if (errno) { perror("read page"); } else { fprintf(stderr, "page read size error.\n"); } goto out; } lkcd_page_header.address = pfn << PAGE_SHIFT_X86_64; lkcd_page_header.size = PAGE_SIZE_X86_64; lkcd_page_header.flags = MKDC_LKCD_DP_RAW; if (write(out_fd, &lkcd_page_header, sizeof(lkcd_page_header)) != sizeof(lkcd_page_header)) { if (errno) { perror("write page header"); } else { fprintf(stderr, "page header write size error.\n"); } goto out; } if (write(out_fd, page_buf, PAGE_SIZE_X86_64) != PAGE_SIZE_X86_64) { if (errno) { perror("write page"); } else { fprintf(stderr, "page write size error.\n"); } goto out; } (*blk_cnt)++; DSP_INDICATOR(sum, *blk_cnt, per); } } if (per != -1) { fprintf(stderr, "\n"); } lkcd_page_header.address = MKDC_LKCD_DP_ADDRESS_END; lkcd_page_header.size = 0; lkcd_page_header.flags = MKDC_LKCD_DP_RAW; if (write(out_fd, &lkcd_page_header, sizeof(lkcd_page_header)) != sizeof(lkcd_page_header)) { if (errno) { perror("write page header"); } else { fprintf(stderr, "page header write size error.\n"); } goto out; } /* * check tailer */ if (read(in_fd, page_buf, PAGE_SIZE_X86_64) != PAGE_SIZE_X86_64) { if (errno) { perror("read tailer"); } else { fprintf(stderr, "tailer read size error.\n"); } goto out; } if (check_tailer(dcache->dvp, (struct dump_version *)page_buf, DUMP_ARCH_X8664, CHECK_HEADER_NOVERBOSE) < 0) { goto out; } /* OK all done */ all_ok = 1; out: if (all_ok) return 0; else return -1; } /* * architecture dependent stuff */ static int convert_header(struct dump_header_x86_64 *dhp, struct mem_seg *msegp, MKDC_LKCD_DH_T *lkcd_dhp, MKDC_LKCD_DHA_X86_64_T *lkcd_dahp, u64 total_page) { int i; int current_cpu; int num_cpus; u32 thread_info; /* * set lkcd dump header */ memset(lkcd_dhp, 0, sizeof(MKDC_LKCD_DH_T)); lkcd_dhp->magic_number = MKDC_LKCD_DH_MAGIC_NUMBER; lkcd_dhp->version = MKDC_LKCD_DH_VERSION_NUMBER; lkcd_dhp->header_size = sizeof(MKDC_LKCD_DH_T); lkcd_dhp->dump_level = 0xf; /* XXX: should define macro ??? f ?????????*/ lkcd_dhp->page_size = msegp->page_size; lkcd_dhp->memory_size = total_page * msegp->page_size; lkcd_dhp->memory_start = (u64)PAGE_OFFSET_X86_64; lkcd_dhp->memory_end = MKDC_LKCD_DH_MAGIC_NUMBER; lkcd_dhp->num_dump_pages = total_page; memcpy(lkcd_dhp->panic_string, dhp->dh_panic_string, DUMP_PANIC_LEN); lkcd_dhp->time.tv_sec = dhp->dh_time.tv_sec; lkcd_dhp->time.tv_usec = dhp->dh_time.tv_nsec / 1000; memcpy(lkcd_dhp->utsname_sysname, dhp->dh_utsname.sysname, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_nodename, dhp->dh_utsname.nodename, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_release, dhp->dh_utsname.release, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_version, dhp->dh_utsname.version, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_machine, dhp->dh_utsname.machine, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_domainname, dhp->dh_utsname.domainname, MKDC_LKCD_DH_UTS_LEN); current_cpu = dhp->dh_dump_cpu; if (current_cpu < 0 || current_cpu > MKDC_LKCD_HDA_MAX_NUM_CPUS_X86_64) { fprintf(stderr, "invalid dump_cpu.\n"); return -1; } lkcd_dhp->current_task = dhp->dh_tasks[current_cpu]; lkcd_dhp->dump_compress = MKDC_LKCD_DH_COMPRESS_NONE; lkcd_dhp->dump_flags = MKDC_LKCD_DH_FLAGS_DISKDUMP; /* lkcd_dhp->dump_device: N/A */ /* * set lkcd dump arch header (x86_64) */ memset(lkcd_dahp, 0, sizeof(MKDC_LKCD_DHA_X86_64_T)); lkcd_dahp->magic_number = MKDC_LKCD_HDA_MAGIC_NUMBER_X86_64; lkcd_dahp->version = MKDC_LKCD_HDA_VERSION_NUMBER_X86_64; lkcd_dahp->header_size = sizeof(MKDC_LKCD_DHA_X86_64_T); lkcd_dahp->regs = dhp->dh_regs[current_cpu]; num_cpus = 0; for( i = 0; i < DUMP_NR_CPUS; i++ ) { if (dhp->dh_tasks[i]) { num_cpus++; } } lkcd_dahp->smp_num_cpus = num_cpus; lkcd_dahp->dumping_cpu = current_cpu; memcpy(lkcd_dahp->smp_regs, dhp->dh_regs, sizeof(struct pt_regs_x86_64) * DUMP_NR_CPUS); memcpy(lkcd_dahp->smp_current_task, dhp->dh_tasks, sizeof(u32) * DUMP_NR_CPUS); for (i = 0; i < DUMP_NR_CPUS; i++) { if (dhp->dh_tasks[i]) { thread_info = dhp->dh_regs[i].rsp & (~8191); lkcd_dahp->stack[i] = thread_info; lkcd_dahp->stack_ptr[i] = thread_info; } } return 0; } --- NEW FILE: mkd_conv_lkcd_i386.c --- /* * mkd_conv/mkd_conv_lkcd_i386.c * * $Id: mkd_conv_lkcd_i386.c,v 1.1 2006/03/03 00:00:01 fkak Exp $ * * Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. * Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. * * 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 (version 2 of the License). * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include "typedefs.h" #include "kernel_x86.h" #include "minik_dump.h" #include "minik_dump_i386.h" #include "lkcd_dump_x86.h" #include "mkd_conv.h" /* buffers */ static char lkcd_header_buf[64 * 1024]; static MKDC_LKCD_DP_T lkcd_page_header; static int convert_header(struct dump_header_i386 *dhp, struct mem_seg *msegp, MKDC_LKCD_DH_T *lkcd_dhp, MKDC_LKCD_DHA_X86_T *lkcd_dahp, u64 total_page); int mkd2lkcd_i386(int in_fd, int out_fd, dump_cache_t *dcache, u64 *blk_cnt) { char *page_buf; int all_ok = 0; int i, per = -1; struct mem_seg *msegp; u64 pfn, end_pfn, sum; DPRINT(("Enter %s(%d)\n", __FUNCTION__,__LINE__)); *blk_cnt = 0; msegp = dcache->dmp; page_buf = dcache->buf; /* * read and check header */ if (check_header(dcache->dvp, DUMP_ARCH_I386, CHECK_HEADER_NOVERBOSE) < 0) { goto out; } /* * convert header and write lkcd_header */ if (dcache->r_dm) { fprintf(stderr, "invalid memseg.\n"); goto out; } if (dcache->blk == 0) { fprintf(stderr, "no page.\n"); goto out; } sum = dcache->blk; if (convert_header((struct dump_header_i386 *)(dcache->dvp), msegp, (MKDC_LKCD_DH_T *)lkcd_header_buf, (MKDC_LKCD_DHA_X86_T *)(lkcd_header_buf + sizeof(MKDC_LKCD_DH_T)), dcache->blk) < 0) { goto out; } if (write(out_fd, lkcd_header_buf, sizeof(lkcd_header_buf)) != sizeof(lkcd_header_buf)) { if (errno) { perror("write header"); } else { fprintf(stderr, "header write size error.\n"); } goto out; } /* * write pages */ for (i = 0, *blk_cnt = 0, per = -1; i < msegp->seg_num; i++) { pfn = msegp->seg_list[i].seg_start_pfn; end_pfn = pfn + msegp->seg_list[i].seg_size; for (; pfn < end_pfn; pfn++) { if (read(in_fd, page_buf, PAGE_SIZE_X86) != PAGE_SIZE_X86) { if (errno) { perror("read page"); } else { fprintf(stderr, "page read size error.\n"); } goto out; } lkcd_page_header.address = pfn << PAGE_SHIFT_X86; lkcd_page_header.size = PAGE_SIZE_X86; lkcd_page_header.flags = MKDC_LKCD_DP_RAW; if (write(out_fd, &lkcd_page_header, sizeof(lkcd_page_header)) != sizeof(lkcd_page_header)) { if (errno) { perror("write page header"); } else { fprintf(stderr, "page header write size error.\n"); } goto out; } if (write(out_fd, page_buf, PAGE_SIZE_X86) != PAGE_SIZE_X86) { if (errno) { perror("write page"); } else { fprintf(stderr, "page write size error.\n"); } goto out; } (*blk_cnt)++; DSP_INDICATOR(sum, *blk_cnt, per); } } if (per != -1) { fprintf(stderr, "\n"); } lkcd_page_header.address = MKDC_LKCD_DP_ADDRESS_END; lkcd_page_header.size = 0; lkcd_page_header.flags = MKDC_LKCD_DP_RAW; if (write(out_fd, &lkcd_page_header, sizeof(lkcd_page_header)) != sizeof(lkcd_page_header)) { if (errno) { perror("write page header"); } else { fprintf(stderr, "page write size error.\n"); } goto out; } /* * check tailer */ if (read(in_fd, page_buf, PAGE_SIZE_X86) != PAGE_SIZE_X86) { if (errno) { perror("read tailer"); } else { fprintf(stderr, "tailer read size error.\n"); } goto out; } if (check_tailer(dcache->dvp, (struct dump_version *)page_buf, DUMP_ARCH_I386, CHECK_HEADER_NOVERBOSE) < 0) { goto out; } /* OK all done */ all_ok = 1; out: if (all_ok) return 0; else return -1; } /* * architecture dependent stuff */ static int convert_header(struct dump_header_i386 *dhp, struct mem_seg *msegp, MKDC_LKCD_DH_T *lkcd_dhp, MKDC_LKCD_DHA_X86_T *lkcd_dahp, u64 total_page) { int i; int current_cpu; int num_cpus; u32 thread_info; /* * set lkcd dump header */ memset(lkcd_dhp, 0, sizeof(MKDC_LKCD_DH_T)); lkcd_dhp->magic_number = MKDC_LKCD_DH_MAGIC_NUMBER; lkcd_dhp->version = MKDC_LKCD_DH_VERSION_NUMBER; lkcd_dhp->header_size = sizeof(MKDC_LKCD_DH_T); lkcd_dhp->dump_level = 0xf; /* XXX: should define macro */ lkcd_dhp->page_size = msegp->page_size; lkcd_dhp->memory_size = total_page; /* XXX */ lkcd_dhp->memory_start = (u64)PAGE_OFFSET_X86; lkcd_dhp->memory_end = MKDC_LKCD_DH_MAGIC_NUMBER; lkcd_dhp->num_dump_pages = total_page; memcpy(lkcd_dhp->panic_string, dhp->dh_panic_string, DUMP_PANIC_LEN); lkcd_dhp->time.tv_sec = dhp->dh_time.tv_sec; lkcd_dhp->time.tv_usec = dhp->dh_time.tv_nsec / 1000; memcpy(lkcd_dhp->utsname_sysname, dhp->dh_utsname.sysname, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_nodename, dhp->dh_utsname.nodename, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_release, dhp->dh_utsname.release, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_version, dhp->dh_utsname.version, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_machine, dhp->dh_utsname.machine, MKDC_LKCD_DH_UTS_LEN); memcpy(lkcd_dhp->utsname_domainname, dhp->dh_utsname.domainname, MKDC_LKCD_DH_UTS_LEN); current_cpu = dhp->dh_dump_cpu; if (current_cpu < 0 || current_cpu > MKDC_LKCD_HDA_MAX_NUM_CPUS_I386) { fprintf(stderr, "invalid dump_cpu.\n"); return -1; } lkcd_dhp->current_task = dhp->dh_tasks[current_cpu]; lkcd_dhp->dump_compress = MKDC_LKCD_DH_COMPRESS_NONE; lkcd_dhp->dump_flags = MKDC_LKCD_DH_FLAGS_DISKDUMP; /* lkcd_dhp->dump_device: N/A */ /* * set lkcd dump arch header (i386) */ memset(lkcd_dahp, 0, sizeof(MKDC_LKCD_DHA_X86_T)); lkcd_dahp->magic_number = MKDC_LKCD_HDA_MAGIC_NUMBER_I386; lkcd_dahp->version = MKDC_LKCD_HDA_VERSION_NUMBER_I386; lkcd_dahp->header_size = sizeof(MKDC_LKCD_DHA_X86_T); /* lkcd_dahp->esp: N/A ? */ /* lkcd_dahp->eip: N/A ? */ /* lkcd_dahp->regs: N/A ? */ num_cpus = 0; for( i = 0; i < DUMP_NR_CPUS; i++ ) { if (dhp->dh_tasks[i]) { num_cpus++; } } lkcd_dahp->smp_num_cpus = num_cpus; lkcd_dahp->dumping_cpu = current_cpu; memcpy(lkcd_dahp->smp_regs, dhp->dh_regs, sizeof(struct pt_regs_x86) * DUMP_NR_CPUS); memcpy(lkcd_dahp->smp_current_task, dhp->dh_tasks, sizeof(u32) * DUMP_NR_CPUS); for (i = 0; i < DUMP_NR_CPUS; i++) { if (dhp->dh_tasks[i]) { thread_info = dhp->dh_regs[i].esp & (~8191); lkcd_dahp->stack[i] = thread_info; lkcd_dahp->stack_ptr[i] = thread_info; } } return 0; } |