#include "elf.h"
	.arch sledgehammer
	.code32
	.equ	FLAT_CODE_SEG,_pmcs-_gdt
	.equ	FLAT_DATA_SEG,_pmds-_gdt
	.equ	MSR_K6_EFER,   0xC0000080
	.equ	EFER_LME,      0x00000100
	.equ	X86_CR4_PAE,   0x00000020
	.equ	CR0_PG,        0x80000000

	.section ".prefix", "ax", @progbits

#define LOAD_ADDR 0x10000
		
	/* ELF Header */
	.globl elf_header
elf_header:	
e_ident:	.byte	0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
e_type:		.short	ET_DYN
e_machine:	.short	EM_X86_64
e_version:	.long	1
e_entry:	.long	LOAD_ADDR + elf_start - elf_header
e_phoff:	.long	elf_program_header - elf_header
e_shoff:	.long	0
e_flags:	.long	0
e_ehsize:	.short	elf_header_end - elf_header
e_phentsize:	.short	ELF32_PHDR_SIZE
e_phnum:	.short	(elf_program_header_end - elf_program_header)/ELF32_PHDR_SIZE
e_shentsize:	.short	0
e_shnum:	.short	0
e_shstrndx:	.short	0
elf_header_end:
	
elf_program_header:
phdr1_p_type:	.long	PT_NOTE
phdr1_p_offset:	.long	elf_note - elf_header
phdr1_p_vaddr:	.long	elf_note
phdr1_p_paddr:	.long	elf_note
phdr1_p_filesz:	.long	elf_note_end - elf_note
phdr1_p_memsz:	.long	elf_note_end - elf_note
phdr1_p_flags:	.long	PF_R | PF_W | PF_X
phdr1_p_align:	.long	0

/* The decompressor */
phdr2_p_type:	.long	PT_LOAD
phdr2_p_offset:	.long	0
phdr2_p_vaddr:	.long	elf_header
phdr2_p_paddr:	.long	LOAD_ADDR
phdr2_p_filesz:	.long	_verbatim_size
phdr2_p_memsz:	.long	_image_size
phdr2_p_flags:	.long	PF_R | PF_W | PF_X
phdr2_p_align:	.long	16

elf_program_header_end:

	.globl elf_note
elf_note:
	.balign 4
	.int 2f - 1f
	.int 4f - 3f
	.int EIN_PROGRAM_NAME
1:	.asciz "ELFBoot"
2:
	.balign 4
3:	
	.asciz "Etherboot"
4:


	.balign 4
	.int 2f - 1f
	.int 4f - 3f
	.int EIN_PROGRAM_VERSION
1:	.asciz "ELFBoot"
2:
	.balign 4
3:	
	.asciz VERSION
4:

#if 0
	.balign 4
	.int 2f - 1f
	.int 4f - 3f
	.int EIN_PROGRAM_CHECKSUM
1:	.asciz "ELFBoot"
2:
	.balign 4
3:	
	.word 0
4:
#endif
	.balign 4
elf_note_end:

elf_start:
	.code64
	/* Reload the gdt to something I know */
	leaq	_gdt(%rip), %rax
	movq	%rax, 0x02 + gdtptr(%rip)
	lgdt	gdtptr(%rip)

	/* Enter 32bit compatibility mode */
	leaq	elf_start32(%rip), %rax
	movl	%eax, 0x00 + elf_start32_addr(%rip)
	ljmp	*elf_start32_addr(%rip)

elf_start32:	
	.code32
	/* Reload the data segments */
	movl	$FLAT_DATA_SEG, %eax
	movl	%eax, %ds
	movl	%eax, %es
	movl	%eax, %ss
	
	/* Disable paging */
	movl	%cr0, %eax
	andl	$~CR0_PG, %eax
	movl	%eax, %cr0

	/* Disable long mode */
	movl	$MSR_K6_EFER, %ecx
	rdmsr
	andl	$~EFER_LME, %eax
	wrmsr

	/* Disable PAE */
	movl	%cr4, %eax
	andl	$~X86_CR4_PAE, %eax
	movl	%eax, %cr4

	/* Save the first argument */
	pushl	%ebx
	jmp	_start

gdtptr:	
	.word	_gdt_end - _gdt -1
	.long	_gdt
	.long	0
_gdt:
elf_start32_addr:
	.long	elf_start32
	.long	FLAT_CODE_SEG
_pmcs:
	/* 32 bit protected mode code segment, base 0 */
	.word	0xffff,0
	.byte	0,0x9f,0xcf,0

_pmds:
	/* 32 bit protected mode data segment, base 0 */
	.word	0xffff,0
	.byte	0,0x93,0xcf,0
_gdt_end:	


	/* Dummy routines to satisfy the build */
	.section ".text16", "ax", @progbits
prefix_exit:

prefix_exit_end:
	.previous
