// File: /workspace/github_c_makefile_star2_O2/gadget114514[P]fatfs-example/fatfs/source/ff.c
// Function: find_volume
static
FRESULT find_volume (	/* FR_OK(0): successful, !=0: any error occurred */
	const TCHAR** path,	/* Pointer to pointer to the path name (drive number) */
	FATFS** rfs,		/* Pointer to pointer to the found filesystem object */
	BYTE mode			/* !=0: Check write protection for write access */
)
{
	BYTE fmt, *pt;
	int vol;
	DSTATUS stat;
	DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4];
	WORD nrsv;
	FATFS *fs;
	UINT i;


	/* Get logical drive number */
	*rfs = 0;
	vol = get_ldnumber(path);
	if (vol < 0) return FR_INVALID_DRIVE;

	/* Check if the filesystem object is valid or not */
	fs = FatFs[vol];					/* Get pointer to the filesystem object */
	if (!fs) return FR_NOT_ENABLED;		/* Is the filesystem object available? */
#if FF_FS_REENTRANT
	if (!lock_fs(fs)) return FR_TIMEOUT;	/* Lock the volume */
#endif
	*rfs = fs;							/* Return pointer to the filesystem object */

	mode &= (BYTE)~FA_READ;				/* Desired access mode, write access or not */
	if (fs->fs_type != 0) {				/* If the volume has been mounted */
		stat = disk_status(fs->pdrv);
		if (!(stat & STA_NOINIT)) {		/* and the physical drive is kept initialized */
			if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) {	/* Check write protection if needed */
				return FR_WRITE_PROTECTED;
			}
			return FR_OK;				/* The filesystem object is valid */
		}
	}

	/* The filesystem object is not valid. */
	/* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */

	fs->fs_type = 0;					/* Clear the filesystem object */
	fs->pdrv = LD2PD(vol);				/* Bind the logical drive and a physical drive */
	stat = disk_initialize(fs->pdrv);	/* Initialize the physical drive */
	if (stat & STA_NOINIT) { 			/* Check if the initialization succeeded */
		return FR_NOT_READY;			/* Failed to initialize due to no medium or hard error */
	}
	if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
		return FR_WRITE_PROTECTED;
	}
#if FF_MAX_SS != FF_MIN_SS				/* Get sector size (multiple sector size cfg only) */
	if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR;
	if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
#endif

	/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */
	bsect = 0;
	fmt = check_fs(fs, bsect);			/* Load sector 0 and check if it is an FAT-VBR as SFD */
	if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) {	/* Not an FAT-VBR or forced partition number */
		for (i = 0; i < 4; i++) {		/* Get partition offset */
			pt = fs->win + (MBR_Table + i * SZ_PTE);
			br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0;
		}
		i = LD2PT(vol);					/* Partition number: 0:auto, 1-4:forced */
		if (i != 0) i--;
		do {							/* Find an FAT volume */
			bsect = br[i];
			fmt = bsect ? check_fs(fs, bsect) : 3;	/* Check the partition */
		} while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4);
	}
	if (fmt == 4) return FR_DISK_ERR;		/* An error occured in the disk I/O layer */
	if (fmt >= 2) return FR_NO_FILESYSTEM;	/* No FAT volume is found */

	/* An FAT volume is found (bsect). Following code initializes the filesystem object */

#if FF_FS_EXFAT
	if (fmt == 1) {
		QWORD maxlba;

		for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ;	/* Check zero filler */
		if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;

		if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM;	/* Check exFAT version (must be version 1.0) */

		if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) {	/* (BPB_BytsPerSecEx must be equal to the physical sector size) */
			return FR_NO_FILESYSTEM;
		}

		maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect;	/* Last LBA + 1 of the volume */
		if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM;	/* (It cannot be handled in 32-bit LBA) */

		fs->fsize = ld_dword(fs->win + BPB_FatSzEx);	/* Number of sectors per FAT */

		fs->n_fats = fs->win[BPB_NumFATsEx];			/* Number of FATs */
		if (fs->n_fats != 1) return FR_NO_FILESYSTEM;	/* (Supports only 1 FAT) */

		fs->csize = 1 << fs->win[BPB_SecPerClusEx];		/* Cluster size */
		if (fs->csize == 0)	return FR_NO_FILESYSTEM;	/* (Must be 1..32768) */

		nclst = ld_dword(fs->win + BPB_NumClusEx);		/* Number of clusters */
		if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM;	/* (Too many clusters) */
		fs->n_fatent = nclst + 2;

		/* Boundaries and Limits */
		fs->volbase = bsect;
		fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
		fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
		if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM;	/* (Volume size must not be smaller than the size requiered) */
		fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);

		/* Check if bitmap location is in assumption (at the first cluster) */
		if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) return FR_DISK_ERR;
		for (i = 0; i < SS(fs); i += SZDIRE) {
			if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break;	/* 81 entry with cluster #2? */
		}
		if (i == SS(fs)) return FR_NO_FILESYSTEM;
#if !FF_FS_READONLY
		fs->last_clst = fs->free_clst = 0xFFFFFFFF;		/* Initialize cluster allocation information */
#endif
		fmt = FS_EXFAT;			/* FAT sub-type */
	} else
#endif	/* FF_FS_EXFAT */
	{
		if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_BytsPerSec must be equal to the physical sector size) */

		fasize = ld_word(fs->win + BPB_FATSz16);		/* Number of sectors per FAT */
		if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);
		fs->fsize = fasize;

		fs->n_fats = fs->win[BPB_NumFATs];				/* Number of FATs */
		if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM;	/* (Must be 1 or 2) */
		fasize *= fs->n_fats;							/* Number of sectors for FAT area */

		fs->csize = fs->win[BPB_SecPerClus];			/* Cluster size */
		if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM;	/* (Must be power of 2) */

		fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt);	/* Number of root directory entries */
		if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM;	/* (Must be sector aligned) */

		tsect = ld_word(fs->win + BPB_TotSec16);		/* Number of sectors on the volume */
		if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);

		nrsv = ld_word(fs->win + BPB_RsvdSecCnt);		/* Number of reserved sectors */
		if (nrsv == 0) return FR_NO_FILESYSTEM;			/* (Must not be 0) */

		/* Determine the FAT sub type */
		sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE);	/* RSV + FAT + DIR */
		if (tsect < sysect) return FR_NO_FILESYSTEM;	/* (Invalid volume size) */
		nclst = (tsect - sysect) / fs->csize;			/* Number of clusters */
		if (nclst == 0) return FR_NO_FILESYSTEM;		/* (Invalid volume size) */
		fmt = 0;
		if (nclst <= MAX_FAT32) fmt = FS_FAT32;
		if (nclst <= MAX_FAT16) fmt = FS_FAT16;
		if (nclst <= MAX_FAT12) fmt = FS_FAT12;
		if (fmt == 0) return FR_NO_FILESYSTEM;

		/* Boundaries and Limits */
		fs->n_fatent = nclst + 2;						/* Number of FAT entries */
		fs->volbase = bsect;							/* Volume start sector */
		fs->fatbase = bsect + nrsv; 					/* FAT start sector */
		fs->database = bsect + sysect;					/* Data start sector */
		if (fmt == FS_FAT32) {
			if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM;	/* (Must be FAT32 revision 0.0) */
			if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM;	/* (BPB_RootEntCnt must be 0) */
			fs->dirbase = ld_dword(fs->win + BPB_RootClus32);	/* Root directory start cluster */
			szbfat = fs->n_fatent * 4;					/* (Needed FAT size) */
		} else {
			if (fs->n_rootdir == 0)	return FR_NO_FILESYSTEM;	/* (BPB_RootEntCnt must not be 0) */
			fs->dirbase = fs->fatbase + fasize;			/* Root directory start sector */
			szbfat = (fmt == FS_FAT16) ?				/* (Needed FAT size) */
				fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
		}
		if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_FATSz must not be less than the size needed) */

#if !FF_FS_READONLY
		/* Get FSInfo if available */
		fs->last_clst = fs->free_clst = 0xFFFFFFFF;		/* Initialize cluster allocation information */
		fs->fsi_flag = 0x80;
#if (FF_FS_NOFSINFO & 3) != 3
		if (fmt == FS_FAT32				/* Allow to update FSInfo only if BPB_FSInfo32 == 1 */
			&& ld_word(fs->win + BPB_FSInfo32) == 1
			&& move_window(fs, bsect + 1) == FR_OK)
		{
			fs->fsi_flag = 0;
			if (ld_word(fs->win + BS_55AA) == 0xAA55	/* Load FSInfo data if available */
				&& ld_dword(fs->win + FSI_LeadSig) == 0x41615252
				&& ld_dword(fs->win + FSI_StrucSig) == 0x61417272)
			{
#if (FF_FS_NOFSINFO & 1) == 0
				fs->free_clst = ld_dword(fs->win + FSI_Free_Count);
#endif
#if (FF_FS_NOFSINFO & 2) == 0
				fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free);
#endif
			}
		}
#endif	/* (FF_FS_NOFSINFO & 3) != 3 */
#endif	/* !FF_FS_READONLY */
	}

	fs->fs_type = fmt;		/* FAT sub-type */
	fs->id = ++Fsid;		/* Volume mount ID */
#if FF_USE_LFN == 1
	fs->lfnbuf = LfnBuf;	/* Static LFN working buffer */
#if FF_FS_EXFAT
	fs->dirbuf = DirBuf;	/* Static directory block scratchpad buuffer */
#endif
#endif
#if FF_FS_RPATH != 0
	fs->cdir = 0;			/* Initialize current directory */
#endif
#if FF_FS_LOCK != 0			/* Clear file lock semaphores */
	clear_lock(fs);
#endif
	return FR_OK;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x20, %rsp
movl %edx, %r14d
movq %rsi, %r12
andq $0x0, (%rsi)
callq 0x143f
testl %eax, %eax
js 0x14e4
movl %eax, %r15d
movl %eax, %eax
leaq 0x6bc2(%rip), %rcx      # 0x8070
movq (%rcx,%rax,8), %rbx
testq %rbx, %rbx
je 0x150e
movq %rbx, (%r12)
cmpb $0x0, (%rbx)
je 0x14e8
movzbl 0x1(%rbx), %edi
callq 0x1274
testb $0x1, %al
jne 0x14e8
movzbl %al, %eax
shll $0x1d, %eax
sarl $0x1f, %eax
andl $0xa, %eax
xorl %ecx, %ecx
testb $0x7e, %r14b
cmovnel %eax, %ecx
jmp 0x1515
pushq $0xb
jmp 0x1514
movb $0x0, (%rbx)
movb %r15b, 0x1(%rbx)
movzbl %r15b, %edi
callq 0x127c
testb $0x1, %al
jne 0x1512
testb $0x7e, %r14b
je 0x1524
movzbl %al, %eax
andl $0x4, %eax
je 0x1524
pushq $0xa
jmp 0x1514
pushq $0xc
jmp 0x1514
pushq $0x3
popq %rcx
movl %ecx, %eax
addq $0x20, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
xorl %r14d, %r14d
movq %rbx, %rdi
xorl %esi, %esi
callq 0x4114
cmpb $0x2, %al
jne 0x1588
movl $0x110, %eax            # imm = 0x110
cmpq $0x130, %rax            # imm = 0x130
je 0x155f
cmpb $0x0, -0x6(%rbx,%rax,2)
je 0x154f
movl -0x2(%rbx,%rax,2), %ecx
jmp 0x1551
xorl %ecx, %ecx
movq %rcx, -0x150(%rbp,%rax)
addq $0x8, %rax
jmp 0x153a
xorl %r15d, %r15d
movq -0x40(%rbp,%r15,8), %r14
testq %r14, %r14
je 0x1579
movq %rbx, %rdi
movq %r14, %rsi
callq 0x4114
jmp 0x157b
movb $0x3, %al
cmpq $0x2, %r15
ja 0x1588
incq %r15
cmpb $0x1, %al
ja 0x1562
cmpb $0x4, %al
jne 0x1590
pushq $0x1
jmp 0x1514
pushq $0xd
popq %rcx
cmpb $0x1, %al
ja 0x1515
cmpw $0x200, 0x63(%rbx)      # imm = 0x200
jne 0x1515
movzwl 0x6e(%rbx), %edi
testq %rdi, %rdi
jne 0x15b3
movl 0x7c(%rbx), %edi
movq %rdi, 0x28(%rbx)
movzbl 0x68(%rbx), %r8d
movb %r8b, 0x2(%rbx)
leal -0x1(%r8), %eax
cmpb $0x1, %al
ja 0x1515
movzbl 0x65(%rbx), %eax
movw %ax, 0xa(%rbx)
leal -0x1(%rax), %edx
movl %eax, %esi
xorb %dl, %sil
cmpb %dl, %sil
jbe 0x1515
movzwl 0x69(%rbx), %r9d
movw %r9w, 0x8(%rbx)
testb $0xf, %r9b
jne 0x1515
movzwl 0x6b(%rbx), %esi
testq %rsi, %rsi
jne 0x1605
movl 0x78(%rbx), %esi
movzwl 0x66(%rbx), %r10d
testq %r10, %r10
je 0x1515
imulq %rdi, %r8
movl %r9d, %r11d
shrl $0x4, %r11d
addq %r10, %r11
addq %r8, %r11
subq %r11, %rsi
jb 0x1515
movzwl %ax, %r15d
movq %rsi, %rax
xorl %edx, %edx
divq %r15
cmpq %r15, %rsi
jb 0x1515
xorl %edx, %edx
cmpq $0xffffff6, %rax        # imm = 0xFFFFFF6
setb %dl
leal (%rdx,%rdx,2), %edx
cmpq $0xfff6, %rax           # imm = 0xFFF6
pushq $0x2
popq %rsi
cmovael %edx, %esi
cmpq $0xff6, %rax            # imm = 0xFF6
pushq $0x1
popq %r15
cmovael %esi, %r15d
testl %r15d, %r15d
je 0x1515
leaq 0x2(%rax), %rdx
movq %rdx, 0x20(%rbx)
movq %r14, 0x30(%rbx)
addq %r14, %r10
movq %r10, 0x38(%rbx)
addq %r14, %r11
movq %r11, 0x48(%rbx)
cmpb $0x3, %r15b
jne 0x16b1
orw 0x82(%rbx), %r9w
jne 0x1515
movl 0x84(%rbx), %eax
movq %rax, 0x40(%rbx)
shlq $0x2, %rdx
jmp 0x16e6
testq %r9, %r9
je 0x1515
addq %r8, %r10
movq %r10, 0x40(%rbx)
leaq -0xff6(%rax), %rsi
cmpq $0xefff, %rsi           # imm = 0xEFFF
ja 0x16d6
addq %rdx, %rdx
jmp 0x16e6
leaq (%rdx,%rdx,2), %rdx
shrq %rdx
andl $0x1, %eax
addq %rdx, %rax
movq %rax, %rdx
addq $0x1ff, %rdx            # imm = 0x1FF
shrq $0x9, %rdx
cmpq %rdx, %rdi
jb 0x1515
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rax, 0x18(%rbx)
movq %rax, 0x10(%rbx)
movb $-0x80, 0x4(%rbx)
cmpb $0x3, %r15b
jne 0x1765
cmpw $0x1, 0x88(%rbx)
jne 0x1765
incq %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1e87
testl %eax, %eax
jne 0x1765
movb $0x0, 0x4(%rbx)
cmpw $0xaa55, 0x256(%rbx)    # imm = 0xAA55
jne 0x1765
cmpl $0x41615252, 0x58(%rbx) # imm = 0x41615252
jne 0x1765
cmpl $0x61417272, 0x23c(%rbx) # imm = 0x61417272
jne 0x1765
movl 0x240(%rbx), %eax
movl 0x244(%rbx), %ecx
movq %rax, 0x18(%rbx)
movq %rcx, 0x10(%rbx)
movb %r15b, (%rbx)
movzwl 0x6909(%rip), %eax      # 0x8078
incl %eax
movw %ax, 0x6900(%rip)       # 0x8078
movw %ax, 0x6(%rbx)
xorl %ecx, %ecx
jmp 0x1515