static int create_header64(DumpState *s)

{

    int ret = 0;

    DiskDumpHeader64 *dh = NULL;

    KdumpSubHeader64 *kh = NULL;

    size_t size;

    int endian = s->dump_info.d_endian;

    uint32_t block_size;

    uint32_t sub_hdr_size;

    uint32_t bitmap_blocks;

    uint32_t status = 0;

    uint64_t offset_note;



    /* write common header, the version of kdump-compressed format is 6th */

    size = sizeof(DiskDumpHeader64);

    dh = g_malloc0(size);



    strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));

    dh->header_version = cpu_convert_to_target32(6, endian);

    block_size = s->page_size;

    dh->block_size = cpu_convert_to_target32(block_size, endian);

    sub_hdr_size = sizeof(struct KdumpSubHeader64) + s->note_size;

    sub_hdr_size = DIV_ROUND_UP(sub_hdr_size, block_size);

    dh->sub_hdr_size = cpu_convert_to_target32(sub_hdr_size, endian);

    /* dh->max_mapnr may be truncated, full 64bit is in kh.max_mapnr_64 */

    dh->max_mapnr = cpu_convert_to_target32(MIN(s->max_mapnr, UINT_MAX),

                                            endian);

    dh->nr_cpus = cpu_convert_to_target32(s->nr_cpus, endian);

    bitmap_blocks = DIV_ROUND_UP(s->len_dump_bitmap, block_size) * 2;

    dh->bitmap_blocks = cpu_convert_to_target32(bitmap_blocks, endian);

    strncpy(dh->utsname.machine, ELF_MACHINE_UNAME, sizeof(dh->utsname.machine));



    if (s->flag_compress & DUMP_DH_COMPRESSED_ZLIB) {

        status |= DUMP_DH_COMPRESSED_ZLIB;

    }

#ifdef CONFIG_LZO

    if (s->flag_compress & DUMP_DH_COMPRESSED_LZO) {

        status |= DUMP_DH_COMPRESSED_LZO;

    }

#endif

#ifdef CONFIG_SNAPPY

    if (s->flag_compress & DUMP_DH_COMPRESSED_SNAPPY) {

        status |= DUMP_DH_COMPRESSED_SNAPPY;

    }

#endif

    dh->status = cpu_convert_to_target32(status, endian);



    if (write_buffer(s->fd, 0, dh, size) < 0) {

        dump_error(s, "dump: failed to write disk dump header.\n");

        ret = -1;

        goto out;

    }



    /* write sub header */

    size = sizeof(KdumpSubHeader64);

    kh = g_malloc0(size);



    /* 64bit max_mapnr_64 */

    kh->max_mapnr_64 = cpu_convert_to_target64(s->max_mapnr, endian);

    kh->phys_base = cpu_convert_to_target64(PHYS_BASE, endian);

    kh->dump_level = cpu_convert_to_target32(DUMP_LEVEL, endian);



    offset_note = DISKDUMP_HEADER_BLOCKS * block_size + size;

    kh->offset_note = cpu_convert_to_target64(offset_note, endian);

    kh->note_size = cpu_convert_to_target64(s->note_size, endian);



    if (write_buffer(s->fd, DISKDUMP_HEADER_BLOCKS *

                     block_size, kh, size) < 0) {

        dump_error(s, "dump: failed to write kdump sub header.\n");

        ret = -1;

        goto out;

    }



    /* write note */

    s->note_buf = g_malloc0(s->note_size);

    s->note_buf_offset = 0;



    /* use s->note_buf to store notes temporarily */

    if (write_elf64_notes(buf_write_note, s) < 0) {

        ret = -1;

        goto out;

    }



    if (write_buffer(s->fd, offset_note, s->note_buf,

                     s->note_size) < 0) {

        dump_error(s, "dump: failed to write notes");

        ret = -1;

        goto out;

    }



    /* get offset of dump_bitmap */

    s->offset_dump_bitmap = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size) *

                             block_size;



    /* get offset of page */

    s->offset_page = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size + bitmap_blocks) *

                     block_size;



out:

    g_free(dh);

    g_free(kh);

    g_free(s->note_buf);



    return ret;

}
