/*
 * include/klib.h
 *
 * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
 */

/**
 ** Main header file for the klib library.
 **
 **/

#ifndef __KLIB_H
#define __KLIB_H

/* Include header files
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>
#include <strings.h>
#include <errno.h>
#include <ctype.h>

extern jmp_buf klib_jbuf;

#ifndef CONFIG_DUMP
#define CONFIG_DUMP 1
#include <dump.h>
#undef CONFIG_DUMP
#else 
#include <dump.h>
#endif

/* Include libklib header files
 */
#include <asm/kl_types.h>
#include <kl_error.h>
#include <kl_btnode.h>
#include <kl_htnode.h>
#include <kl_queue.h>
#include <kl_alloc.h>
#include <kl_stringtab.h>
#include <kl_typeinfo.h>
#include <kl_task.h>
#include <kl_mem.h>
#include <asm/kl_arch.h>
#include <kl_stabs.h>
#include <kl_sym.h>

#ifndef TRUE
#define TRUE	1
#endif
#ifndef FALSE
#define FALSE	0
#endif

/* Values for arch
 */
#define ARCH_ALPHA	1
#define ARCH_ARM	2
#define ARCH_I386	3
#define ARCH_IA64	4
#define ARCH_M68K	5
#define ARCH_MIPS	6
#define ARCH_MIPS64     7
#define ARCH_PPC        8
#define ARCH_S390       9
#define ARCH_SH        10
#define ARCH_SPARK     11
#define ARCH_SPARK64   12
#define ARCH_S390X     13

/* Defines for linux_release
 */
#define LINUX_2_2_16    0x020210
#define LINUX_2_2_17    0x020211
#define LINUX_2_4_0 	0x020400
#define LINUX_2_2_X(R) (((R) & 0xffff00) == 0x020200)
#define LINUX_2_4_X(R) (((R) & 0xffff00) == 0x020400)
#define LINUX_2_4_4     0x020404
#define LINUX_2_4_15    0x02040f

extern lkcdinfo_t lkcdinfo;
extern unsigned long NUM_PHYSPAGES;
extern kaddr_t MEM_MAP;
extern kaddr_t deftask;
extern kaddr_t KL_HIGH_MEMORY;
extern paddr_t KL_INIT_MM;

#define KL_ARCH                 lkcdinfo.arch
#define KL_PTRSZ                lkcdinfo.ptrsz
#define KL_NBPW                 (KL_PTRSZ/8)
#define KL_BYTE_ORDER           lkcdinfo.byte_order
#define KL_LINUX_RELEASE        lkcdinfo.linux_release
#define KL_PAGE_SHIFT           lkcdinfo.page_shift
#define KL_PAGE_SIZE            lkcdinfo.page_size
#define KL_PAGE_MASK            lkcdinfo.page_mask
#define KL_PAGE_OFFSET          lkcdinfo.page_offset
#define KL_STACK_OFFSET         lkcdinfo.stack_offset
#define IS_BIG_ENDIAN()         (KL_BYTE_ORDER == BIG_ENDIAN)
#define IS_LITTLE_ENDIAN()      (KL_BYTE_ORDER == LITTLE_ENDIAN)

/*
 * Dump Constants:
 *
 * These are constants used by the kernel dump code that are
 * often, but not necessarly, architecture independent. The
 * are not likely to change between kernels for the same arch.
 */
int  dump_page_size;
int  dump_page_shift;
long dump_page_mask;
int  dump_header_offset;
int  dump_header_size;
int  dump_buffer_size;



extern void bp(void);
extern void *malloc(size_t);
extern void *realloc(void *, size_t);
extern void *calloc(size_t, size_t);
extern void *xmalloc(size_t);
extern void *alloc_block(int, int, void *);
extern void *realloc_block(void *, int, int, void *);
extern void *dup_block(void *, int, void *);
extern void *str_to_block(char *, int, void *);

#define K_TEMP		1
#define K_PERM		2

/* Macros that eliminate the offset paramaters to the kl_uint() and kl_int()
 * functions (just makes things cleaner looking)
 */
#define KL_UINT(p, s, m) kl_uint(p, s, m, 0)
#define KL_INT(p, s, m) kl_int(p, s, m, 0)

/* Macros for translating strings into long numeric values depending 
 * on the base of 's'.
 */
#define GET_VALUE(s, value) kl_get_value(s, NULL, 0, value)
#define GET_HEX_VALUE(s) (kaddr_t)strtoull(s, (char**)NULL, 16)
#define GET_DEC_VALUE(s) (unsigned)strtoull(s, (char**)NULL, 10)
#define GET_OCT_VALUE(s) (unsigned)strtoull(s, (char**)NULL, 8)

/* Flag that tells kl_is_valid_kaddr() to perform a word aligned check
 */
#define WORD_ALIGN_FLAG         1

#define ADDR_TO_PGNO(addr) ((addr - KL_PAGE_OFFSET) >> KL_PAGE_SHIFT);

/* Generalized macros for pointing at different data types at particular
 * offsets in kernel structs.
 */
#define K_ADDR(p, s, f)   ((uaddr_t)(p) + kl_member_offset(s, f))
#define K_PTR(p, s, f)    ((void *)K_ADDR(p, s, f))
#define CHAR(p, s, f)     ((char *)K_ADDR(p, s, f))

#define PTRSZ32 ((KL_PTRSZ == 32) ? 1 : 0)
#define PTRSZ64 ((KL_PTRSZ == 64) ? 1 : 0)

/* Struct klib_s, contains all the information necessary for accessing
 * information in the kernel. A pointer to a klib_t struct will be
 * returned from libkern_init() if core dump analysis (or live system
 * analysis) is possible.
 *
 */
typedef struct klib_s {
	int		k_flags;     /* Flags pertaining to klib_s struct */
	meminfo_t      *k_meminfo;
	maplist_t      *k_symmap;
	kltype_t       *k_typeinfo;
} klib_t;

extern klib_t *KLP;

#define MIP KLP->k_meminfo
#define STP KLP->k_symmap

/* Struct that contains the sizes of commonly used kernel structures.
 */
typedef struct struct_sizes_s {
        int     task_struct_sz;
        int     mm_struct_sz;
	int	page_sz;
	int	module_sz;
	int	new_utsname_sz;
	int	_dump_header_s_sz;
	int	_dump_header_asm_s_sz;
} struct_sizes_t;

extern struct_sizes_t struct_sizes;
	        
#define TASK_STRUCT_SZ		(struct_sizes.task_struct_sz)
#define MM_STRUCT_SZ		(struct_sizes.mm_struct_sz)
#define PAGE_SZ        		(struct_sizes.page_sz)
#define MODULE_SZ        	(struct_sizes.module_sz)
#define NEW_UTSNAME_SZ        	(struct_sizes.new_utsname_sz)
#define _DUMP_HEADER_S_SZ 	(struct_sizes._dump_header_s_sz)
#define _DUMP_HEADER_ASM_S_SZ   (struct_sizes._dump_header_asm_s_sz)

/* Function prototypes
 */
void kl_binary_print(uint64_t, FILE *);
void kl_print_bit_value(void *, int, int, int, int, FILE *);
void kl_print_char(void *, int, FILE *);
void kl_print_uchar(void *, int, FILE *);
void kl_print_int2(void *, int, FILE *);
void kl_print_uint2(void *, int, FILE *);
void kl_print_int4(void *, int, FILE *);
void kl_print_uint4(void *, int, FILE *);
void kl_print_float4(void *, int, FILE *);
void kl_print_int8(void *, int, FILE *);
void kl_print_uint8(void *, int, FILE *);
void kl_print_float8(void *, int, FILE *);
void kl_print_base(void *, int, int, int, FILE *);
void kl_print_string(char *, FILE *);

void kl_reset_error(void);

int kl_init_klib(
        char *                  /* map file name */,
        char *                  /* dump file name */,
        char *                  /* namelist file name */,
        int                   	/* rwflag flag (/dev/mem only) */);

void kl_free_klib(
	klib_t *		/* Pointer to klib_s struct */);

int
kl_dump_retrieve(
	char *			/* dumpdev name */,
	char *			/* dumpdir name */,
	int			/* progress flag (zero or non-zero) */,
	int			/* debug flag (zero or non-zero) */);

int
kl_dump_erase(
	char *			/* dumpdev name */);

uint64_t
kl_strtoull(
	char *			/* string containing numeric value */, 
	char **			/* pointer to pointer to bad char */, 
	int 			/* base */);

int
kl_get_value(
	char *			/* param */, 
	int *			/* mode pointer */, 
	int 			/* number of elements */, 
	uint64_t *		/* pointer to value */);

uint64_t 
kl_get_bit_value(
	void *			/* pointer to value */,
	int 			/* byte_size */, 
	int 			/* bit_size */, 
	int 			/* bit_offset */);

int kl_sig_setup(void);

void kl_set_curnmlist(
	int 			/* index  of namelist */);

int kl_open_namelist(
	char *			/* name of namelist */,
	int 			/* flags */);

int kl_is_valid_kaddr(
	kaddr_t 		/* Address to test */,
	void *			/* pointer to mmap */, 
	int 			/* flags */);

int cmpinit(
	meminfo_t *		/* mip */, 
	int 			/* fd */, 
	char *			/* indexname */, 
	int 			/* flags */);

void kl_print_dump_header(FILE *);

kaddr_t kaddr_to_ptr(kaddr_t);

int kl_get_module(char *, kaddr_t *, void **);
int kl_get_structure(kaddr_t,  char *, size_t *, void **);

#endif /* __KLIB_H */
