2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
10 * Under ARM iOS quadwords are long-aligned, however in AROS (according to AAPCS)
11 * they are quad-aligned. This macro turns on some tricks which bypass this problem
13 #define HOST_LONG_ALIGNED
17 * Under i386 we pick up MacOS' libSystem.dylib instead of Simulator's libSystem.dylib,
18 * so we have to use special versions of certain functions. We can't simply #define _DARWIN_NO_64_BIT_INODE
19 * because iOS SDK forbids this (in iOS inode_t is always 64-bit wide)
21 #define INODE64_SUFFIX "$INODE64"
24 /* Correspondingly, there's no struct stat64. Use struct stat instead. */
29 * Use 32-bit inode_t on Darwin. Otherwise we are expected to use "stat$INODE64"
30 * instead of "stat" function which is available only on MacOS 10.6.
32 #define _DARWIN_NO_64_BIT_INODE
33 /* This enables struct stat64 definition */
34 #define _DARWIN_C_SOURCE /* For Darwin */
35 #define _LARGEFILE64_SOURCE /* For Linux */
38 #ifndef INODE64_SUFFIX
39 #define INODE64_SUFFIX
42 /* Prevents struct timeval redefinition */
43 #define timeval sys_timeval
57 #include <aros/debug.h>
58 #include <aros/symbolsets.h>
59 #include <devices/trackdisk.h>
60 #include <exec/errors.h>
61 #include <proto/exec.h>
62 #include <proto/hostlib.h>
63 #include <proto/intuition.h>
64 #include <proto/kernel.h>
66 #ifdef HOST_LONG_ALIGNED
72 #include "hostdisk_host.h"
73 #include "hostdisk_device.h"
75 static ULONG
error(int unixerr
)
77 D(bug("hostdisk: UNIX error %d\n", unixerr
));
85 return TDERR_DriveInUse
;
88 return TDERR_WriteProt
;
91 return TDERR_NotSpecified
;
95 ULONG
Host_Open(struct unit
*Unit
)
97 struct HostDiskBase
*hdskBase
= Unit
->hdskBase
;
100 D(bug("hostdisk: Host_Open(%s)\n", Unit
->filename
));
105 Unit
->file
= hdskBase
->iface
->open(Unit
->filename
, O_RDWR
, 0755, &err
);
107 err
= *hdskBase
->errnoPtr
;
109 if (err
== EBUSY
|| err
== EROFS
)
111 /* This allows to work on Darwin, at least in read-only mode */
112 D(bug("hostdisk: EBUSY, retrying with read-only access\n", Unit
->filename
, Unit
->file
, err
));
113 Unit
->flags
= UNIT_READONLY
;
115 Unit
->file
= hdskBase
->iface
->open(Unit
->filename
, O_RDONLY
, 0755);
117 err
= *hdskBase
->errnoPtr
;
122 if (Unit
->file
== -1)
124 D(bug("hostdisk: Error %d\n", err
));
132 void Host_Close(struct unit
*Unit
)
134 struct HostDiskBase
*hdskBase
= Unit
->hdskBase
;
136 D(bug("hostdisk: Close device %s\n", Unit
->n
.ln_Name
));
137 D(bug("hostdisk: HostLibBase 0x%p, close() 0x%p\n", HostLibBase
, hdskBase
->iface
->close
));
141 hdskBase
->iface
->close(Unit
->file
);
147 LONG
Host_Read(struct unit
*Unit
, APTR buf
, ULONG size
, ULONG
*ioerr
)
149 struct HostDiskBase
*hdskBase
= Unit
->hdskBase
;
152 D(bug("hostdisk: Read %u bytes\n", size
));
156 ret
= hdskBase
->iface
->read(Unit
->file
, buf
, size
);
158 err
= *hdskBase
->errnoPtr
;
168 LONG
Host_Write(struct unit
*Unit
, APTR buf
, ULONG size
, ULONG
*ioerr
)
170 struct HostDiskBase
*hdskBase
= Unit
->hdskBase
;
173 D(bug("hostdisk: Write %u bytes\n", size
));
177 ret
= hdskBase
->iface
->write(Unit
->file
, buf
, size
);
179 err
= *hdskBase
->errnoPtr
;
189 ULONG
Host_Seek(struct unit
*Unit
, ULONG pos
)
191 return Host_Seek64(Unit
, pos
, 0);
194 ULONG
Host_Seek64(struct unit
*Unit
, ULONG pos
, ULONG pos_hi
)
196 struct HostDiskBase
*hdskBase
= Unit
->hdskBase
;
199 D(bug("hostdisk: Seek to block 0x%08X%08X (%llu)\n", pos_hi
, pos
, (((UQUAD
)pos_hi
) << 32) + pos
));
202 * Host OS is usually not reentrant.
203 * All host OS calls should be protected by global lock (since hostlib.resource v3).
207 res
= LSeek(Unit
->file
, pos
, pos_hi
, SEEK_SET
);
212 return (res
== -1) ? TDERR_SeekError
: 0;
215 static ULONG
InternalGetGeometry(int file
, struct DriveGeometry
*dg
, struct HostDiskBase
*hdskBase
)
222 res
= hdskBase
->iface
->fstat64(file
, &st
);
223 err
= *hdskBase
->errnoPtr
;
229 if (S_ISBLK(st
.st_mode
))
232 * For real block devices we can use IOCTL-based function. It will provide better info.
233 * This routine returns UNIX error code, for simplicity.
235 err
= Host_DeviceGeometry(file
, dg
, hdskBase
);
237 /* If this routine is not implemented, use fstat() (worst case) */
242 D(bug("hostdisk: Image file length: %ld\n", st
.st_size
));
244 dg
->dg_TotalSectors
= st
.st_size
/ dg
->dg_SectorSize
;
245 dg
->dg_Cylinders
= dg
->dg_TotalSectors
; /* LBA, CylSectors == 1 */
250 D(bug("hostdisk: InternalGetGeometry(): UNIX error %u\n", err
));
254 ULONG
Host_GetGeometry(struct unit
*Unit
, struct DriveGeometry
*dg
)
256 int err
= InternalGetGeometry(Unit
->file
, dg
, Unit
->hdskBase
);
261 int Host_ProbeGeometry(struct HostDiskBase
*hdskBase
, char *name
, struct DriveGeometry
*dg
)
267 file
= hdskBase
->iface
->open(name
, O_RDONLY
, 0755);
275 res
= InternalGetGeometry(file
, dg
, hdskBase
);
279 hdskBase
->iface
->close(file
);
287 extern const char Hostdisk_LibName
[];
289 static const char *libcSymbols
[] =
302 #ifdef HOST_OS_android
307 "fstat64" INODE64_SUFFIX
,
308 "stat64" INODE64_SUFFIX
,
313 static BOOL
CheckArch(const char *Component
, const char *MyArch
, const char *SystemArch
)
315 const char *arg
[3] = {Component
, MyArch
, SystemArch
};
317 D(bug("hostdisk: My architecture: %s, kernel architecture: %s\n", arg
[1], arg
[2]));
319 if (strcmp(arg
[1], arg
[2]))
321 struct IntuitionBase
*IntuitionBase
;
323 IntuitionBase
= (struct IntuitionBase
*)OpenLibrary("intuition.library", 36);
326 struct EasyStruct es
=
328 sizeof (struct EasyStruct
),
330 "Incompatible architecture",
331 "Used version of %s is built for use\n"
332 "with %s architecture, but your\n"
333 "system architecture is %s.",
337 EasyRequestArgs(NULL
, &es
, NULL
, (RAWARG
)arg
);
339 CloseLibrary(&IntuitionBase
->LibNode
);
344 D(bug("hostdisk: Architecture check done\n"));
348 static int Host_Init(struct HostDiskBase
*hdskBase
)
353 * This device is disk-based and it can travel from disk to disk.
354 * In order to prevent unexplained crashes we check that system architecture
355 * is the architecture we were built for.
357 APTR KernelBase
= OpenResource("kernel.resource");
362 arch
= (STRPTR
)KrnGetSystemAttr(KATTR_Architecture
);
366 if (!CheckArch(Hostdisk_LibName
, AROS_ARCHITECTURE
, arch
))
369 hdskBase
->KernelHandle
= HostLib_Open(LIBC_NAME
, NULL
);
370 if (!hdskBase
->KernelHandle
)
373 hdskBase
->iface
= (struct HostInterface
*)HostLib_GetInterface(hdskBase
->KernelHandle
, libcSymbols
, &r
);
374 if ((!hdskBase
->iface
) || r
)
377 hdskBase
->errnoPtr
= hdskBase
->iface
->__error();
379 hdskBase
->DiskDevice
= DISK_DEVICE
;
380 hdskBase
->unitBase
= DISK_BASE
;
385 ADD2INITLIB(Host_Init
, 0);