void dumpsys(struct dumperinfo *di) { struct sparc64_dump_hdr hdr; vm_size_t size, totsize, hdrsize; int error, i, nreg; /* Calculate dump size. */ size = 0; nreg = sparc64_nmemreg; for (i = 0; i < sparc64_nmemreg; i++) size += sparc64_memreg[i].mr_size; /* Account for the header size. */ hdrsize = roundup2(sizeof(hdr) + sizeof(struct sparc64_dump_reg) * nreg, DEV_BSIZE); size += hdrsize; totsize = size + 2 * sizeof(kdh); if (totsize > di->mediasize) { printf("Insufficient space on device (need %ld, have %ld), " "refusing to dump.\n", (long)totsize, (long)di->mediasize); error = ENOSPC; goto fail; } /* Determine dump offset on device. */ dumplo = di->mediaoffset + di->mediasize - totsize; mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_SPARC64_VERSION, size, di->blocksize); printf("Dumping %lu MB (%d chunks)\n", (u_long)(size >> 20), nreg); /* Dump leader */ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); if (error) goto fail; dumplo += sizeof(kdh); /* Dump the private header. */ hdr.dh_hdr_size = hdrsize; hdr.dh_tsb_pa = tsb_kernel_phys; hdr.dh_tsb_size = tsb_kernel_size; hdr.dh_tsb_mask = tsb_kernel_mask; hdr.dh_nregions = nreg; if (buf_write(di, (char *)&hdr, sizeof(hdr)) != 0) goto fail; dumppos = hdrsize; /* Now, write out the region descriptors. */ for (i = 0; i < sparc64_nmemreg; i++) { error = reg_write(di, sparc64_memreg[i].mr_start, sparc64_memreg[i].mr_size); if (error != 0) goto fail; } buf_flush(di); /* Dump memory chunks. */ for (i = 0; i < sparc64_nmemreg; i++) { error = blk_dump(di, sparc64_memreg[i].mr_start, sparc64_memreg[i].mr_size); if (error != 0) goto fail; } /* Dump trailer */ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); if (error) goto fail; /* Signal completion, signoff and exit stage left. */ dump_write(di, NULL, 0, 0, 0); printf("\nDump complete\n"); return; fail: /* XXX It should look more like VMS :-) */ printf("** DUMP FAILED (ERROR %d) **\n", error); }
/* * Commit text dump to disk. */ void textdump_dumpsys(struct dumperinfo *di) { off_t dumplen, trailer_offset; if (di->blocksize != TEXTDUMP_BLOCKSIZE) { printf("Dump partition block size (%ju) not textdump " "block size (%ju)", (uintmax_t)di->blocksize, (uintmax_t)TEXTDUMP_BLOCKSIZE); return; } /* * We don't know a priori how large the dump will be, but we do know * that we need to reserve space for metadata and that we need two * dump headers. Also leave room for one ustar header and one block * of data. */ if (di->mediasize < SIZEOF_METADATA + 2 * sizeof(kdh)) { printf("Insufficient space on dump partition.\n"); return; } textdump_error = 0; /* * Position the start of the dump so that we'll write the kernel dump * trailer immediately before the end of the partition, and then work * our way back. We will rewrite this header later to reflect the * true size if things go well. */ textdump_offset = di->mediasize - sizeof(kdh); textdump_saveoff(&trailer_offset); mkdumpheader(&kdh, TEXTDUMPMAGIC, KERNELDUMP_TEXT_VERSION, 0, TEXTDUMP_BLOCKSIZE); (void)textdump_writenextblock(di, (char *)&kdh); /* * Write a series of files in ustar format. */ if (textdump_do_ddb) db_capture_dump(di); #ifdef INCLUDE_CONFIG_FILE if (textdump_do_config) textdump_dump_config(di); #endif if (textdump_do_msgbuf) textdump_dump_msgbuf(di); if (textdump_do_panic && panicstr != NULL) textdump_dump_panic(di); if (textdump_do_version) textdump_dump_version(di); /* * Now that we know the true size, we can write out the header, then * seek back to the end and rewrite the trailer with the correct * size. */ dumplen = trailer_offset - (textdump_offset + TEXTDUMP_BLOCKSIZE); mkdumpheader(&kdh, TEXTDUMPMAGIC, KERNELDUMP_TEXT_VERSION, dumplen, TEXTDUMP_BLOCKSIZE); (void)textdump_writenextblock(di, (char *)&kdh); textdump_restoreoff(trailer_offset); (void)textdump_writenextblock(di, (char *)&kdh); /* * Terminate the dump, report any errors, and clear the pending flag. */ if (textdump_error == 0) (void)dump_write(di, NULL, 0, 0, 0); if (textdump_error == ENOSPC) printf("Insufficient space on dump partition\n"); else if (textdump_error != 0) printf("Error %d writing dump\n", textdump_error); else printf("Textdump complete.\n"); textdump_pending = 0; }