#ifndef __GIXLINUXSETUP_H
#define __GIXLINUXSETUP_H



#define SYSCONFIG_PATH "/etc/sysconfig"

/*
 
/etc/sysconfig/ifconfig.eth0 
 
ONBOOT=yes
IFACE=eth0
SERVICE=ipv4-static
IP=192.168.0.84
GATEWAY=192.168.0.1
PREFIX=24
BROADCAST=192.168.0.255
IP6=2001:4100::123
PREFIX6=80
*/





#define GIX_VERSION "GIX-LINUX 2.00"
#define OPTION_Y_OFFSET ((rows / 2) - (options * 2 / 2))
#define OPTION_X_OFFSET ((cols /2 ) - (longest_option/2))

#define DEBUG_LOGFILE "/tmp/gixsetup.log"

#define SUBWIN_X_OFFSET 1
#define SUBWIN_Y_OFFSET 1

#define ALARM_FATAL      2
#define ALARM_WARNING    1
#define ALARM_INFO       0
#define ALARM_OKCANCEL   3
#define ALARM_INPUT      4
#define ALARM_ERROR      5

#define ANSWER_OK        1
#define ANSWER_CANCEL    0


#define BASE2_COLOR_NORMAL   1
#define BASE2_COLOR_ERROR    2
#define BASE_COLOR_NORMAL    0
#define BASE_COLOR_ERROR     6

#define ALARM_COLOR_FATAL    2
#define ALARM_COLOR_ERROR    2
#define ALARM_COLOR_INFO     3
#define ALARM_COLOR_WARNING  4
#define ALARM_COLOR_OKCANCEL 5
#define ALARM_COLOR_INPUT    ALARM_COLOR_WARNING
#define RUNNER_COLOR         4


#define BSIZE 512
#define DHCP_TIMEOUT 5

#define SYS_TRIGGER_CTL "/proc/sys/kernel/sysrq"
#define SYS_TRIGGER     "/proc/sysrq-trigger"
#define VFAT_COMMAND    "/usr/sbin/mkfs.fat"
#define EXT4_COMMAND    "/usr/sbin/mkfs.ext4"

#define EXT4_MAGIC 0xEF53

#pragma pack(push,1)

#define MODE_ROOT_DISKS 0
#define MODE_FS_DISKS   1


#define TBUFSIZE 2048
#define XZ_CHUNK_SIZE (TBUFSIZE * 2)


#define FTP_DEBUG 0
#define FTP_SERVER "gixl.internic.at"
#define FTP_USER "gixl2"
#define FTP_PWD  "gixl2"
#define FTP_EFI_PATH "/efi"
#define FTP_CONNECT_TIMEOUT (10 * 1000)

#define RAID_CMD    "/usr/sbin/mdadm"
#define RAID_0_CMD  "/usr/sbin/mdadm --create /dev/md%d --force --level=0  --metadata=1.2 --assume-clean  --raid-devices=%d %s"
#define RAID_1_CMD  "/usr/sbin/mdadm --create /dev/md%d --force --level=1  --metadata=1.2 --assume-clean  --raid-devices=%d %s"
#define RAID_10_CMD "/usr/sbin/mdadm --create /dev/md%d --force --level=10 --metadata=1.2 --assume-clean  --raid-devices=%d %s"


struct bootp_packet {
        u_int8_t op;
        u_int8_t htype;
        u_int8_t hlen;
        u_int8_t hops;
        u_int32_t xid;
        u_int16_t secs;
        u_int16_t flags;
        u_int32_t ciaddr;
        u_int32_t yiaddr;
        u_int32_t siaddr;
        u_int32_t giaddr;
        u_int8_t chaddr[16];
        u_int8_t sname[64];
        u_int8_t file[128];
};

struct gix_udphdr
{
  u_int16_t source;           /* source port */
  u_int16_t dest;           /* destination port */
  u_int16_t len;            /* udp length */
  u_int16_t check;             /* udp checksum */
};

struct tar_header {
	unsigned char filename[100];
	unsigned char filemode[8];
	unsigned char ownerid[8];
	unsigned char groupid[8];
	unsigned char filesize[12];
	unsigned char modtime[12];
	unsigned char checksum[8];
	unsigned char typeflag[1];
	unsigned char linkname[100];
	unsigned char magic[6];
	unsigned char version[2];
	unsigned char ownername[32]; // Not used!
	unsigned char groupname[32]; // Not used!
	unsigned char devmajor[8]; 
	unsigned char devminor[8]; 
	unsigned char filenameprefix[155]; 
};




struct ext4_super_block {
    __le32 s_inodes_count;         // Total number of inodes
    __le32 s_blocks_count_lo;      // Total number of blocks (lower 32 bits)
    __le32 s_r_blocks_count_lo;    // Reserved blocks count (lower 32 bits)
    __le32 s_free_blocks_count_lo; // Free blocks count (lower 32 bits)
    __le32 s_free_inodes_count;    // Total number of free inodes
    __le32 s_first_data_block;     // Number of the first data block
    __le32 s_log_block_size;       // Block size
    __le32 s_log_cluster_size;     // Cluster size
    __le32 s_blocks_per_group;     // Number of blocks per group
    __le32 s_clusters_per_group;   // Number of clusters per group
    __le32 s_inodes_per_group;     // Number of inodes per group
    __le32 s_mtime;                // Mount time
    __le32 s_wtime;                // Write time
    __le16 s_mnt_count;            // Number of mounts since last check
    __le16 s_max_mnt_count;        // Maximum mounts before a check
    __le16 s_magic;                // Magic signature
    __le16 s_state;                // File system state
    __le16 s_errors;               // Behaviour when detecting errors
    __le16 s_minor_rev_level;      // Minor revision level
    __le32 s_lastcheck;            // Time of last check
    __le32 s_checkinterval;        // Maximum time between checks
    __le32 s_creator_os;           // OS that created the filesystem
    __le32 s_rev_level;            // Revision level
    __le16 s_def_resuid;           // Default UID for reserved blocks
    __le16 s_def_resgid;           // Default GID for reserved blocks
    
    /* The following fields are for dynamic allocation of the superblock */
    __le32 s_first_ino;            // First inode
    __le16 s_inode_size;           // Size of inode structure
    __le16 s_block_group_nr;       // Block group number of this superblock
    __le32 s_feature_compat;       // Compatible feature set
    __le32 s_feature_incompat;     // Incompatible feature set
    __le32 s_feature_ro_compat;    // Read-only compatible feature set
    __u8  s_uuid[16];              // 128-bit UUID for volume
    char  s_volume_name[16];       // Volume name
    char  s_last_mounted[64];      // Directory where the filesystem was last mounted
    __le32 s_algorithm_usage_bitmap; // For compression algorithms
    __u8  s_prealloc_blocks;       // Number of blocks to preallocate
    __u8  s_prealloc_dir_blocks;   // Number of blocks to preallocate for directories
    __le16 s_reserved_gdt_blocks;  // Reserved GDT blocks for filesystem expansion
    __u8  s_journal_uuid[16];      // UUID of journal superblock
    __le32 s_journal_inum;         // Inode number of journal file
    __le32 s_journal_dev;          // Device number of journal file
    __le32 s_last_orphan;          // Start of list of orphaned inodes to delete
    __le32 s_hash_seed[4];         // HTREE hash seed
    __u8  s_def_hash_version;      // Default hash version to use for directories
    __u8  s_jnl_backup_type;       // Type of journal backup
    __le16 s_desc_size;            // Size of group descriptors
    __le32 s_default_mount_opts;   // Default mount options
    __le32 s_first_meta_bg;        // First metatdata block group
    __le32 s_mkfs_time;            // Time when the filesystem was created
    __le32 s_jnl_blocks[17];       // Backup of the first part of the journal inode

    __le32 s_free_blocks_count_hi; // Total number of free blocks (upper 32 bits)
    __le32 s_blocks_count_hi;      // Total number of blocks (upper 32 bits)
    __le32 s_r_blocks_count_hi;    // Reserved blocks count (upper 32 bits)
    
    __le16 s_min_extra_isize;      // All inodes have at least # bytes
    __le16 s_want_extra_isize;     // New inodes should reserve # bytes
    __le32 s_flags;                // Miscellaneous flags

    __le16 s_raid_stride;          // RAID stride
    __le16 s_mmp_interval;         // # seconds to wait in MMP checking
    __le64 s_mmp_block;            // Block for multi-mount protection
    __le32 s_raid_stripe_width;    // blocks nubmber of the stripe
    __u8  s_log_groups_per_flex;   // FLEX_BG
    __u8  s_reserved_char_pad;
    __u16 s_reserved_pad;
    __le64 s_kbytes_written;       // Number of lifetime kilobytes written

    __le32 s_snapshot_inum;        // Inode number of active snapshot
    __le32 s_snapshot_id;          // Sequential ID of active snapshot
    __le64 s_snapshot_r_blocks_count; // Reserved blocks for active snapshot’s future use
    __le32 s_snapshot_list;        // List of all snapshots

    __le32 s_error_count;          // Number of FS errors
    __le32 s_first_error_time;     // First time an error happened
    __le32 s_first_error_ino;      // Inode involved in first error
    __le32 s_first_error_block;    // Block involved of first error
    __u8  s_first_error_func[32];  // Function where the error happened
    __le32 s_first_error_line;     // Line number where error happened
    __le32 s_last_error_time;      // Most recent error happened
    __le32 s_last_error_ino;       // Inode involved in last error
    __le32 s_last_error_line;      // Line number where error happened
    __u8  s_last_error_func[32];   // Function where the error happened

    __le32 s_mount_opts[64];
    __le32 s_usr_quota_inum;       // Inode number of user quota file
    __le32 s_grp_quota_inum;       // Inode number of group quota file
    __le32 s_overhead_clusters;    // Number of clusters needed for soft updates 

    __le32 s_backup_bgs[64];       // For online resize

    __le32 s_reserved[164];        // Padding to the end of the block
};


struct _part {
	char devname[16];
};


struct _raid {
	char devname[16];
	int level;
	struct _part  *part;
	int parts;
	u_int64_t size;
};


struct in6_ifreq {
    struct in6_addr ifr6_addr;
    u_int32_t ifr6_prefixlen;
    unsigned int ifr6_ifindex;
};      





void _debug_logger(char *__file__,int __line__,const char *fmt, ...);
#define debug_logger(fmt, ...) _debug_logger(__FILE__,__LINE__,fmt, ##__VA_ARGS__)

char *showsize(u_int64_t size);

char *_getdevname(char *path, int major, int minor);


void update_raidlist();
struct _raid *checkraidmember(char *devname);
struct _raid *getraid(char *devname);

struct _interface {
        char name[16];
	char service[64];
        unsigned char ip4[4];
        int  prefixlen_ip4;
	unsigned char gw_ip4[4];
	unsigned char broadcast_ip4[4];
        unsigned char ip6[16];
	unsigned char gw_ip6[16];
        int  prefixlen_ip6;
        int  active;
};


struct _interface *getinterface(char *sysconfigpath, char *ifname);
int write_interface(char *sysconfigpath,struct _interface *iff);


char *display_ipv4(unsigned char *addr, int addr_len, char *output);
char *display_ipv6(unsigned char *addr, int addr_len, char *output);

unsigned char *gix_apply_netmask_ipv6(unsigned char *netmask, unsigned char *ipv6, unsigned char *result);
unsigned char *gix_apply_netmask_ipv4(unsigned char *netmask, unsigned char *ipv4, unsigned char *result);
unsigned char *gix_genmask_ipv6(int prefixlen, unsigned char *netmask);
unsigned char *gix_genmask_ipv4(int prefix_len, unsigned char *result);
unsigned char *gix_gen_broadcast_ipv4(unsigned char *ipv4, int prefix_len, unsigned char *result);



int is_zero(unsigned char *field,int len);


// EFI Stuff...


struct _filepath {
        unsigned char type;
        unsigned char subtype;
        unsigned short length;
        unsigned char *data;
};


struct _mdp {
	// 4.1 starts here
	u_int16_t partnumber;
	u_int64_t starting_lba;
	u_int64_t partition_size;
	unsigned char signature[16];
	unsigned char mbr_type[1]; // MBR or GPT
	unsigned char signature_type[1]; // GUID or signature	
	// 4.4 starts here
	unsigned char file_path[1024]; // The boot-file itself (bzImage, setup.efi, ...) UTF16 encoded filepath \0\0 terminated
	
};




struct _efidisk {
        char device[32];
        int partno; // From /dev/sdaX
        struct fdisk_context *ctx;
        struct fdisk_partition *pa;
        struct fdisk_parttype *pt;
        struct fdisk_label *label;
        u_int64_t start;
        u_int64_t size;
        char uuid[512];
        unsigned char serial[16];
        char label_name[512];
        int label_type;
};

int create_efi_boot_entry(struct _efidisk *ef,unsigned char *bootlabel,unsigned char *bootimage,unsigned char *bootargs,u_int16_t *bootorder, int bootorders, int bootsel);


#define HANDLER_RETURN_STAY           0
#define HANDLER_RETURN_ESCAPE         1
#define HANDLER_RETURN_CURRENT_SELECT 2

void get_boot_guid(char *uuid);

struct _efivar {
	u_int16_t entrynr;
	int active;
	int boot_order;
	size_t size;
        char name[256];
	u_int32_t attributes;
	u_int16_t fileflags;
        wchar_t description[1024];
        int description_len;
        struct _filepath *filepath;
        int  filepaths;
        unsigned char optional_data[1024];
	int remain;
	unsigned char *remain_data;
	u_int16_t *bootorder; // Only set in _efivar[0]!!!
	int bootorders; 
	unsigned char dummy[2];
	// Type 4 here (if appicable)
	struct _mdp *mdp; // Media-Device Path
};

void encode_utf16(const wchar_t *input);
size_t decode_utf16(const uint16_t *input, wchar_t *output, size_t out_size);




#define EFI_VARIABLE_NON_VOLATILE                    0x00000001
#define EFI_VARIABLE_BOOTSERVICE_ACCESS              0x00000002
#define EFI_VARIABLE_RUNTIME_ACCESS                  0x00000004
#define EFI_VARIABLE_HARDWARE_ERROR_RECORD           0x00000008
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS      0x00000010
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE  0x00000020
#define EFI_VARIABLE_APPEND_WRITE                    0x00000040
#define EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS   0x00000080

int load_efi_vars(struct _efivar **efi);
void dump_efi(struct _efivar *ef);
char *gix_hexdump(unsigned char *data, int data_len, char *rett);

void efi_write_boot_order_file(char *fname, u_int16_t *bootorder, int bootorders);

void efi_write_boot_order(u_int16_t *bootorder, int bootorders);

void uuid_to_serial(char *uuid, unsigned char *serial);


#define EFI_PATH "/sys/firmware/efi/efivars"

char *generate_guid(char *newguid);

uint64_t swap_bytes(uint64_t value);

#pragma pack(pop)

int run_program(char *exe, char **arg,char *caption, char *final_prompt);

char *get_tag(char *filename, char *tag);


#endif
