summaryrefslogtreecommitdiffstats
path: root/src/drivers/disk/floppy.c
diff options
context:
space:
mode:
authorMichael Brown2005-03-08 19:53:11 +0100
committerMichael Brown2005-03-08 19:53:11 +0100
commit3d6123e69ab879c72ff489afc5bf93ef0b7a94ce (patch)
tree9f3277569153a550fa8d81ebd61bd88f266eb8da /src/drivers/disk/floppy.c
downloadipxe-3d6123e69ab879c72ff489afc5bf93ef0b7a94ce.tar.gz
ipxe-3d6123e69ab879c72ff489afc5bf93ef0b7a94ce.tar.xz
ipxe-3d6123e69ab879c72ff489afc5bf93ef0b7a94ce.zip
Initial revision
Diffstat (limited to 'src/drivers/disk/floppy.c')
-rw-r--r--src/drivers/disk/floppy.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/drivers/disk/floppy.c b/src/drivers/disk/floppy.c
new file mode 100644
index 000000000..9cb0a22da
--- /dev/null
+++ b/src/drivers/disk/floppy.c
@@ -0,0 +1,88 @@
+#if (TRY_FLOPPY_FIRST > 0)
+
+/*
+ * 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, or (at
+ * your option) any later version.
+ */
+
+#include "etherboot.h"
+
+#define BOOTSECT ((char *)0x7C00)
+#define BOOTSIG ((unsigned short *)BOOTSECT)[0xFF]
+#define PARTTAB ((partentry *)(BOOTSECT+0x1BE))
+
+typedef struct partentry {
+ unsigned char flags;
+ unsigned char start_head;
+ unsigned char start_sector;
+ unsigned char start_cylinder;
+ unsigned char type;
+ unsigned char end_head;
+ unsigned char end_sector;
+ unsigned char end_cylinder;
+ unsigned long offset;
+ unsigned long length;
+} partentry;
+
+static unsigned int disk_read_retry(int dev,int c,int h,int s)
+{
+ int retry = 3,rc;
+
+ while (retry-- && (rc = pcbios_disk_read(dev,c,h,s,BOOTSECT)) != 0);
+ if (BOOTSIG != 0xAA55) {
+ printf("not a boot sector");
+ return(0xFFFF); }
+ return(rc);
+}
+
+int bootdisk(int dev,int part)
+{
+ int rc;
+
+ disk_init();
+ if ((rc = disk_read_retry(dev,0,0,1)) != 0) {
+ readerr:
+ if (rc != 0xFFFF)
+ printf("read error (%#hhX)",rc/256);
+ return(0); }
+ if (part) {
+ partentry *ptr;
+
+ if (part >= 5) {
+ int i;
+ for (i = 0, ptr = PARTTAB; ptr->type != 5; ptr++)
+ if (++i == 4) {
+ printf("partition not found");
+ return(0); }
+ if ((rc = disk_read_retry(dev,
+ ptr->start_cylinder,
+ ptr->start_head,
+ ptr->start_sector)) != 0)
+ goto readerr;
+ part -= 4; }
+ if (!(ptr = PARTTAB-1+part)->type) {
+ printf("empty partition");
+ return(0); }
+ if ((rc = disk_read_retry(dev,
+ ptr->start_cylinder,
+ ptr->start_head,
+ ptr->start_sector)) != 0)
+ goto readerr; }
+ cleanup();
+ gateA20_unset();
+ /* Set %edx to device number to emulate BIOS
+ Fortunately %edx is not used after this */
+ __asm__("movl %0,%%edx" : : "g" (dev));
+ xstart((unsigned long)BOOTSECT, 0, 0);
+ return(0);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */