/*
 * Copyright (C) 2009 Juergen Beisert, Pengutronix
 *
 * This code was inspired by the GRUB2 project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 *
 */

/**
 * @file
 * @brief Loading the barebox image from a disk drive in LBA mode
 */

/**
 * @fn void real_start(void)
 * @brief A very simple and small loader to fetch all required sectors
 * from the boot media.
 */


	.file "boot_hdisk.S"
	.code16

	/*
	 * These symbols are generated by the linker, because they need a
	 * special layout. This layout is needed to be able to setup this
	 * bootloader by patching the binary when it gets stored into the
	 * master boot record.
	 */
	.extern indirect_sector_lba
	.extern boot_stack
	.extern start_pre_uboot
	.extern boot_disk
	.section .boot_code, "ax"

	.globl real_start
	.type real_start, @function

real_start:

	xorw %ax, %ax	/* set up %ds and %ss as offset from 0 */
	movw %ax, %ds
	movw %ax, %ss

	/* set up the REAL stack */
	movw $boot_stack, %sp

	sti		/* we're safe again */

	/* save drive reference first thing! */
	movb %dl, boot_disk
	pushw %dx

	movw $notification_string, %si
	call output_message

	/*
	 * This boot code only supports LBA. We fail here, if the BIOS
	 * does not support LBA for the harddisk
	 */

	/* check if LBA is supported */
	movb $0x41, %ah
	movw $0x55aa, %bx
	int $0x13

	/*
	 *  %dl may have been clobbered by INT 13, AH=41H.
	 *  This happens, for example, with AST BIOS 1.04.
	 */
	popw %dx
	pushw %dx

	/* stop if no LBA support */
	jc no_lba
	cmpw $0xaa55, %bx
	jne no_lba
	andw $1, %cx
	jz no_lba

lba_mode:
	/*
	 * Load the indirect sector. Its content is ready for use,
	 * provided by the installer
	 */
	movw $indirect_sector_lba, %si
	movb $0x42, %ah
	int $0x13
	jc no_lba	/* error? Then die */

	/*
	 * Now loop through all valid entries in the indirect sector
	 */
	movw $indirect_area, %si

load_loop:
	/*
	 * Stop if this "Disk Address Packet Structure" is invalid
	 * We call it invalid, if the size member is zero. If it is invalid
	 * we are optimistic and calling the loaded image
	 */
	movw (%si), %ax
	cmpw $0x0000, %ax
	je start_main

	/*
	 * Load this entry
	 */
	movb $0x42, %ah
	int $0x13
	jc no_lba

	addw (%si), %si	/* next entry */
	cmpw $indirect_area + 512, %si
	jne load_loop
	/*
	 * fall through to start u-boot.
	 */
start_main:
	movw $jmp_string, %si
	call output_message
	jmp start_pre_uboot
/*
 * die if there is no LBA support
 */
no_lba:	movw $chs_string, %si
	call output_message
	hlt

/*
 * message: write the string pointed to by %si
 *
 *   WARNING: trashes %si, %ax, and %bx
 */

/*
 * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
 *	%ah = 0xe	%al = character
 *	%bh = page	%bl = foreground color (graphics modes)
 */

1:
	movw	$0x0001, %bx
	movb	$0xe, %ah
	int	$0x10		/* display this char */

output_message:
	lodsb
	cmpb	$0, %al
	jne	1b	/* if not end of string, next char */
	ret

/* ---------------------------------------------------------------------- */

	.section .boot_data

notification_string:	.asciz "UBOOT2 "
chs_string:	.asciz "CHS "
jmp_string:	.asciz "JMP "

