Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_dump.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <machine/dump.h> | #include <machine/dump.h> | ||||
#include <machine/elf.h> | #include <machine/elf.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/pcb.h> | #include <machine/pcb.h> | ||||
CTASSERT(sizeof(struct kerneldumpheader) == 512); | CTASSERT(sizeof(struct kerneldumpheader) == 512); | ||||
/* | |||||
* Don't touch the first SIZEOF_METADATA bytes on the dump device. This | |||||
* is to protect us from metadata and to protect metadata from us. | |||||
*/ | |||||
#define SIZEOF_METADATA (64*1024) | |||||
#define MD_ALIGN(x) roundup2((off_t)(x), PAGE_SIZE) | #define MD_ALIGN(x) roundup2((off_t)(x), PAGE_SIZE) | ||||
off_t dumplo; | off_t dumplo; | ||||
/* Handle buffered writes. */ | /* Handle buffered writes. */ | ||||
static size_t fragsz; | static size_t fragsz; | ||||
struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; | struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; | ||||
▲ Show 20 Lines • Show All 276 Lines • ▼ Show 20 Lines | #endif | ||||
dumpsize = 0L; | dumpsize = 0L; | ||||
ehdr.e_phnum = dumpsys_foreach_chunk(cb_size, &dumpsize) + | ehdr.e_phnum = dumpsys_foreach_chunk(cb_size, &dumpsize) + | ||||
DUMPSYS_NUM_AUX_HDRS; | DUMPSYS_NUM_AUX_HDRS; | ||||
hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize; | hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize; | ||||
fileofs = MD_ALIGN(hdrsz); | fileofs = MD_ALIGN(hdrsz); | ||||
dumpsize += fileofs; | dumpsize += fileofs; | ||||
hdrgap = fileofs - roundup2((off_t)hdrsz, di->blocksize); | hdrgap = fileofs - roundup2((off_t)hdrsz, di->blocksize); | ||||
/* Determine dump offset on device. */ | |||||
if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2 + | |||||
kerneldumpcrypto_dumpkeysize(di->kdc)) { | |||||
error = ENOSPC; | |||||
goto fail; | |||||
} | |||||
dumplo = di->mediaoffset + di->mediasize - dumpsize; | |||||
dumplo -= di->blocksize * 2; | |||||
dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc); | |||||
/* Initialize kernel dump crypto. */ | |||||
error = kerneldumpcrypto_init(di->kdc); | |||||
if (error) | |||||
goto fail; | |||||
mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize, | mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize, | ||||
kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize); | kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize); | ||||
printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20, | printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20, | ||||
ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); | ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); | ||||
/* Dump leader */ | error = dump_start(di, &kdh, &dumplo); | ||||
error = dump_write_header(di, &kdh, 0, dumplo); | if (error != 0) | ||||
if (error) | |||||
goto fail; | goto fail; | ||||
dumplo += di->blocksize; | |||||
/* Dump key */ | |||||
error = dump_write_key(di, 0, dumplo); | |||||
if (error) | |||||
goto fail; | |||||
dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); | |||||
/* Dump ELF header */ | /* Dump ELF header */ | ||||
error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); | error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump program headers */ | /* Dump program headers */ | ||||
error = dumpsys_foreach_chunk(cb_dumphdr, di); | error = dumpsys_foreach_chunk(cb_dumphdr, di); | ||||
if (error < 0) | if (error < 0) | ||||
Show All 14 Lines | #endif | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump memory chunks (updates dumplo) */ | /* Dump memory chunks (updates dumplo) */ | ||||
error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di); | error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di); | ||||
if (error < 0) | if (error < 0) | ||||
goto fail; | goto fail; | ||||
/* Dump trailer */ | error = dump_finish(di, &kdh, dumplo); | ||||
error = dump_write_header(di, &kdh, 0, dumplo); | if (error != 0) | ||||
if (error) | |||||
goto fail; | goto fail; | ||||
dumplo += di->blocksize; | |||||
/* Signal completion, signoff and exit stage left. */ | |||||
dump_write(di, NULL, 0, 0, 0); | |||||
printf("\nDump complete\n"); | printf("\nDump complete\n"); | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
if (error < 0) | if (error < 0) | ||||
error = -error; | error = -error; | ||||
if (error == ECANCELED) | if (error == ECANCELED) | ||||
printf("\nDump aborted\n"); | printf("\nDump aborted\n"); | ||||
else if (error == ENOSPC) | else if (error == E2BIG) | ||||
printf("\nDump failed. Partition too small.\n"); | printf("\nDump failed. Partition too small.\n"); | ||||
else | else | ||||
printf("\n** DUMP FAILED (ERROR %d) **\n", error); | printf("\n** DUMP FAILED (ERROR %d) **\n", error); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif | #endif |