/*
 * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
 */
#include <lcrash.h>

extern char map[];
extern char dump[];
extern char namelist[];

/*
 * do_report() -- generate an lcrash report.
 */
int
do_report(int flags, FILE *ofp)
{
	int is_live_dump = 0;
	time_t curtime;
	dump_header_t dump_header;
	dump_header_asm_t dump_header_asm;

	if(MIP->core_type == s390_core) 
		return S390_DO_REPORT(flags,ofp);

	/* first, make sure this isn't a live system 
	 */
	if (MIP->core_type != reg_core) {
		fprintf(ofp, "Error: a report can only be generated for "
			"dump files!\n");
		return(1);
	}

	/* get the dump header 
	 */
	if (lseek(MIP->core_fd, 0, SEEK_SET) < 0) {
		fprintf(ofp, "Error: Cannot lseek() to get the dump header "
			"from the dump file!\n");
		return(1);
	}

	if (read(MIP->core_fd, (char *)&dump_header,
		sizeof(dump_header)) != sizeof(dump_header)) {
			fprintf(ofp, "Error: Cannot read() dump header "
				"from dump file!\n");
			return(1);
	}

	if (read(MIP->core_fd, (char *)&dump_header_asm,
		sizeof(dump_header_asm_t)) != sizeof(dump_header_asm_t)) {
			fprintf(ofp, "Error: Cannot read() architecture-"
				"specific dump header from dump file!\n");
			return(1);
	}

	if (dump_header.dh_magic_number == DUMP_MAGIC_LIVE) {
		is_live_dump = 1; 
	} else if (dump_header.dh_magic_number != DUMP_MAGIC_NUMBER) {
		fprintf(ofp, "Error: DUMP_MAGIC_NUMBER in dump header "
			"is invalid!\n");
			return(1);
	}

	if (dump_header_asm.dha_magic_number != DUMP_ASM_MAGIC_NUMBER) {
		fprintf(ofp, "Error: DUMP_ASM_MAGIC_NUMBER in dump header "
			"is invalid!\n");
			return(1);
	}

	fprintf(ofp,
		"=======================\n"
		"LCRASH CORE FILE REPORT\n"
		"=======================\n\n");

	curtime = time((time_t *)0);
	fprintf(ofp, "GENERATED ON:\n    %s\n\n", ctime(&curtime));

	if (is_live_dump) {
		fprintf(ofp, "LIVE DUMP CREATED:\n    %s\n\n",
			ctime(&(dump_header.dh_time.tv_sec)));
	} else {
		fprintf(ofp, "TIME OF CRASH:\n    %s\n\n",
			ctime(&(dump_header.dh_time.tv_sec)));
		if (dump_header.dh_panic_string[0] != 0) {
			fprintf(ofp, "PANIC STRING:\n    %s\n\n",
				dump_header.dh_panic_string);
		} else {
			fprintf(ofp, "PANIC STRING:\n    (none)\n\n");
		}
	}

	fprintf(ofp, "MAP:\n    %s\n\n", map);
	fprintf(ofp, "DUMP:\n    %s\n\n", dump);
	fprintf(ofp, "KERNTYPES:\n    %s\n\n", namelist);

	fprintf(ofp,
		"================\n"
		"COREFILE SUMMARY\n"
		"================\n\n");

	/*
	 * Indicate the general nature of the event leading up to the
	 * dump. For dumps initiated by the kernel, there is currently
	 * only one type of crash dump -- the one that occurs due to a 
	 * software kernel problem.  Later, we need to add code to deal 
	 * with NMIs, hardware failures, etc. It's possible that the
	 * dump was generated by an application from live system memory. 
	 */
	if (is_live_dump) {
		fprintf(ofp, 
			"    This is a dump from a live, running system.\n\n");
	} else {
		fprintf(ofp, 
			"    The system died due to a software failure.\n\n");
	}

	fprintf(ofp,
		"===================\n"
		"UTSNAME INFORMATION\n"
		"===================\n\n");

	fprintf(ofp, "   sysname : %s\n", dump_header.dh_utsname_sysname);
	fprintf(ofp, "  nodename : %s\n", dump_header.dh_utsname_nodename);
	fprintf(ofp, "   release : %s\n", dump_header.dh_utsname_release);
	fprintf(ofp, "   version : %s\n", dump_header.dh_utsname_version);
	fprintf(ofp, "   machine : %s\n", dump_header.dh_utsname_machine);
	fprintf(ofp, "domainname : %s\n", dump_header.dh_utsname_domainname);
	fprintf(ofp, "\n");

	fprintf(ofp,
		"===============\n"
		"LOG BUFFER DUMP\n"
		"===============\n\n");

	/* print out the system log
	 */
	print_log_buf(ofp);
	fprintf(ofp, "\n\n");

	fprintf(ofp,
		"====================\n"
		"CURRENT SYSTEM TASKS\n"
		"====================\n\n");

	print_active_tasks(flags, ofp);
	fprintf(ofp, "\n");

	fprintf(ofp,
		"===========================\n"
		"STACK TRACE OF FAILING TASK\n"
		"===========================\n\n");

	if (dumptask_trace((kaddr_t)dump_header.dh_current_task, 
			&dump_header_asm, flags, ofp)) {
		return(1);
	}
	return(0);
}
