// File: /workspace/github_c_makefile_star2_O2/lb3361[P]dosfs/ff.c
// Function: create_partition
static FRESULT create_partition (
	BYTE drv,			/* Physical drive number */
	const LBA_t plst[],	/* Partition list */
	BYTE sys,			/* System ID (for only MBR, temp setting) */
	BYTE* buf			/* Working buffer for a sector */
)
{
	UINT i, cy;
	LBA_t sz_drv;
	DWORD sz_drv32, s_lba32, n_lba32;
	BYTE *pte, hd, n_hd, sc, n_sc;

	/* Get drive size */
	if (disk_ioctl(drv, GET_SECTOR_COUNT, &sz_drv) != RES_OK) return FR_DISK_ERR;

#if FF_LBA64
	if (sz_drv >= FF_MIN_GPT) {	/* Create partitions in GPT */
		WORD ss;
		UINT sz_pt, pi, si, ofs;
		DWORD bcc, rnd, align;
		QWORD s_lba64, n_lba64, sz_pool, s_bpt;
		static const BYTE gpt_mbr[16] = {0x00, 0x00, 0x02, 0x00, 0xEE, 0xFE, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};

#if FF_MAX_SS != FF_MIN_SS
		if (disk_ioctl(drv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;	/* Get sector size */
		if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
#else
		ss = FF_MAX_SS;
#endif
		rnd = GET_FATTIME();			/* Random seed */
		align = GPT_ALIGN / ss;			/* Partition alignment [sector] */
		sz_pt = GPT_ITEMS * SZ_GPTE / ss;	/* Size of PT [sector] */
		s_bpt = sz_drv - sz_pt - 1;		/* Backup PT start sector */
		s_lba64 = 2 + sz_pt;			/* First allocatable sector */
		sz_pool = s_bpt - s_lba64;		/* Size of allocatable area */
		bcc = 0xFFFFFFFF; n_lba64 = 1;
		pi = si = 0;	/* partition table index, size table index */
		do {
			if (pi * SZ_GPTE % ss == 0) mem_set(buf, 0, ss);	/* Clean the buffer if needed */
			if (n_lba64 != 0) {	/* Is the size table not termintated? */
				s_lba64 = (s_lba64 + align - 1) & ((QWORD)0 - align);	/* Align partition start */
				n_lba64 = plst[si++];	/* Get a partition size */
				if (n_lba64 <= 100) {	/* Is the size in percentage? */
					n_lba64 = sz_pool * n_lba64 / 100;
					n_lba64 = (n_lba64 + align - 1) & ((QWORD)0 - align);	/* Align partition end (only if in percentage) */
				}
				if (s_lba64 + n_lba64 > s_bpt) {	/* Clip at end of the pool */
					n_lba64 = (s_lba64 < s_bpt) ? s_bpt - s_lba64 : 0;
				}
			}
			if (n_lba64 != 0) {		/* Add a partition? */
				ofs = pi * SZ_GPTE % ss;
				mem_cpy(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16);	/* Partition GUID (Microsoft Basic Data) */
				rnd = make_rand(rnd, buf + ofs + GPTE_UpGuid, 16);		/* Unique partition GUID */
				st_qword(buf + ofs + GPTE_FstLba, s_lba64);				/* Partition start LBA */
				st_qword(buf + ofs + GPTE_LstLba, s_lba64 + n_lba64 - 1);	/* Partition end LBA */
				s_lba64 += n_lba64;		/* Next partition LBA */
			}
			if ((pi + 1) * SZ_GPTE % ss == 0) {		/* Write the buffer if it is filled up */
				for (i = 0; i < ss; bcc = crc32(bcc, buf[i++])) ;	/* Calculate table check sum */
				if (disk_write(drv, buf, 2 + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR;		/* Primary table */
				if (disk_write(drv, buf, s_bpt + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR;	/* Secondary table */
			}
		} while (++pi < GPT_ITEMS);

		/* Create primary GPT header */
		mem_set(buf, 0, ss);
		mem_cpy(buf + GPTH_Sign, "EFI PART" "\0\0\1\0" "\x5C\0\0", 16);	/* Signature, version (1.0) and size (92) */
		st_dword(buf + GPTH_PtBcc, ~bcc);				/* Table check sum */
		st_qword(buf + GPTH_CurLba, 1);					/* LBA of this header */
		st_qword(buf + GPTH_BakLba, sz_drv - 1);		/* LBA of another header */
		st_qword(buf + GPTH_FstLba, 2 + sz_pt);			/* LBA of first allocatable sector */
		st_qword(buf + GPTH_LstLba, s_bpt - 1);			/* LBA of last allocatable sector */
		st_dword(buf + GPTH_PteSize, SZ_GPTE);			/* Size of a table entry */
		st_dword(buf + GPTH_PtNum, GPT_ITEMS);			/* Number of table entries */
		st_dword(buf + GPTH_PtOfs, 2);					/* LBA of this table */
		rnd = make_rand(rnd, buf + GPTH_DskGuid, 16);	/* Disk GUID */
		for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ;	/* Calculate header check sum */
		st_dword(buf + GPTH_Bcc, ~bcc);					/* Header check sum */
		if (disk_write(drv, buf, 1, 1) != RES_OK) return FR_DISK_ERR;

		/* Create secondary GPT header */
		st_qword(buf + GPTH_CurLba, sz_drv - 1);		/* LBA of this header */
		st_qword(buf + GPTH_BakLba, 1);					/* LBA of another header */
		st_qword(buf + GPTH_PtOfs, s_bpt);				/* LBA of this table */
		st_dword(buf + GPTH_Bcc, 0);
		for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ;	/* Calculate header check sum */
		st_dword(buf + GPTH_Bcc, ~bcc);					/* Header check sum */
		if (disk_write(drv, buf, sz_drv - 1, 1) != RES_OK) return FR_DISK_ERR;

		/* Create protective MBR */
		mem_set(buf, 0, ss);
		mem_cpy(buf + MBR_Table, gpt_mbr, 16);			/* Create a GPT partition */
		st_word(buf + BS_55AA, 0xAA55);
		if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR;

	} else
#endif
	{					/* Create partitions in MBR */
		sz_drv32 = (DWORD)sz_drv;
		n_sc = N_SEC_TRACK;		/* Determine drive CHS without any consideration of the drive geometry */
		for (n_hd = 8; n_hd != 0 && sz_drv32 / n_hd / n_sc > 1024; n_hd *= 2) ;
		if (n_hd == 0) n_hd = 255;	/* Number of heads needs to be <256 */

		mem_set(buf, 0, FF_MAX_SS);	/* Clear MBR */
		pte = buf + MBR_Table;	/* Partition table in the MBR */
		for (i = 0, s_lba32 = n_sc; i < 4 && s_lba32 != 0 && s_lba32 < sz_drv32; i++, s_lba32 += n_lba32) {
			n_lba32 = (DWORD)plst[i];	/* Get partition size */
			if (n_lba32 <= 100) n_lba32 = (n_lba32 == 100) ? sz_drv32 : sz_drv32 / 100 * n_lba32;	/* Size in percentage? */
			if (s_lba32 + n_lba32 > sz_drv32 || s_lba32 + n_lba32 < s_lba32) n_lba32 = sz_drv32 - s_lba32;	/* Clip at drive size */
			if (n_lba32 == 0) break;	/* End of table or no sector to allocate? */

			st_dword(pte + PTE_StLba, s_lba32);		/* Start LBA */
			st_dword(pte + PTE_SizLba, n_lba32);	/* Number of sectors */
			pte[PTE_System] = sys;					/* System type */

			cy = (UINT)(s_lba32 / n_sc / n_hd);		/* Start cylinder */
			hd = (BYTE)(s_lba32 / n_sc % n_hd);		/* Start head */
			sc = (BYTE)(s_lba32 % n_sc + 1);		/* Start sector */
			pte[PTE_StHead] = hd;
			pte[PTE_StSec] = (BYTE)((cy >> 2 & 0xC0) | sc);
			pte[PTE_StCyl] = (BYTE)cy;

			cy = (UINT)((s_lba32 + n_lba32 - 1) / n_sc / n_hd);	/* End cylinder */
			hd = (BYTE)((s_lba32 + n_lba32 - 1) / n_sc % n_hd);	/* End head */
			sc = (BYTE)((s_lba32 + n_lba32 - 1) % n_sc + 1);	/* End sector */
			pte[PTE_EdHead] = hd;
			pte[PTE_EdSec] = (BYTE)((cy >> 2 & 0xC0) | sc);
			pte[PTE_EdCyl] = (BYTE)cy;

			pte += SZ_PTE;		/* Next entry */
		}

		st_word(buf + BS_55AA, 0xAA55);		/* MBR signature */
		if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR;	/* Write it to the MBR */
	}

	return FR_OK;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rcx, %rbx
movl %edx, %r15d
movq %rsi, %r13
movl %edi, %r14d
pushq $0x1
popq %r12
leaq 0x18(%rsp), %rdx
movl %r12d, %esi
callq 0x2930
testl %eax, %eax
je 0x9fdf
movl %r12d, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x18(%rsp), %r12
cmpq $0x10000000, %r12       # imm = 0x10000000
movq %r13, 0x28(%rsp)
jb 0xa256
callq 0x2992
movl %eax, 0x10(%rsp)
movq 0x18(%rsp), %rcx
leaq -0x21(%rcx), %rax
movq %rax, 0x20(%rsp)
movq %rcx, 0x30(%rsp)
leaq -0x43(%rcx), %rax
movq %rax, 0x38(%rsp)
pushq $0x1
popq %r12
pushq $0x22
popq %r13
pushq $-0x1
popq %rbp
movzbl %r14b, %eax
movl %eax, 0x14(%rsp)
xorl %r15d, %r15d
movl $0x0, 0xc(%rsp)
movl %r15d, %r14d
shll $0x7, %r14d
andl $0x180, %r14d           # imm = 0x180
jne 0xa058
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
xorl %esi, %esi
callq 0x2110
testq %r12, %r12
je 0xa127
movl 0xc(%rsp), %esi
movl %esi, %eax
movq 0x28(%rsp), %rcx
movq (%rcx,%rax,8), %rax
cmpq $0x64, %rax
ja 0xa097
imulq 0x38(%rsp), %rax
xorl %edx, %edx
pushq $0x64
popq %rcx
divq %rcx
addq $0x7ff, %rax            # imm = 0x7FF
movabsq $0x7fffffffffff800, %rcx # imm = 0x7FFFFFFFFFFF800
andq %rcx, %rax
addq $0x7ff, %r13            # imm = 0x7FF
andq $-0x800, %r13           # imm = 0xF800
incl %esi
movl %esi, 0xc(%rsp)
leaq (%rax,%r13), %rcx
movq 0x20(%rsp), %rdx
movq %rdx, %r12
subq %r13, %r12
movl $0x0, %esi
cmovbq %rsi, %r12
cmpq %rdx, %rcx
cmovbeq %rax, %r12
testq %r12, %r12
je 0xa127
movl %r14d, %r14d
leaq (%rbx,%r14), %rdi
leaq 0x22f3(%rip), %rsi      # 0xc3d0
pushq $0x10
popq %rdx
callq 0x60c7
leaq (%rbx,%r14), %rsi
addq $0x10, %rsi
movl 0x10(%rsp), %edi
callq 0xacca
movl %eax, 0x10(%rsp)
leaq (%rbx,%r14), %rdi
addq $0x20, %rdi
movq %r13, %rsi
callq 0x68e6
leaq (%rbx,%r14), %rdi
addq $0x28, %rdi
leaq (%r12,%r13), %r14
leaq (%r12,%r13), %rsi
decq %rsi
callq 0x68e6
movq %r14, %r13
jmp 0xa12a
xorl %r12d, %r12d
leal 0x1(%r15), %r14d
testb $0x3, %r14b
jne 0xa19e
movq %r13, 0x40(%rsp)
xorl %r13d, %r13d
cmpq $0x200, %r13            # imm = 0x200
je 0xa158
movzbl (%rbx,%r13), %esi
incq %r13
movl %ebp, %edi
callq 0xaca5
movl %eax, %ebp
jmp 0xa13c
shrl $0x2, %r15d
leal 0x2(%r15), %edx
movl 0x14(%rsp), %r13d
movl %r13d, %edi
movq %rbx, %rsi
pushq $0x1
popq %rcx
callq 0x28af
testl %eax, %eax
jne 0xa435
movl %r15d, %edx
addq 0x20(%rsp), %rdx
movl %r13d, %edi
movq %rbx, %rsi
pushq $0x1
popq %rcx
callq 0x28af
testl %eax, %eax
movq 0x40(%rsp), %r13
jne 0xa435
movl %r14d, %r15d
cmpl $0x80, %r14d
jne 0xa039
xorl %r15d, %r15d
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
xorl %esi, %esi
callq 0x2110
leaq 0x22f1(%rip), %rsi      # 0xc4b8
pushq $0x10
popq %rdx
movq %rbx, %rdi
callq 0x60c7
notl %ebp
movl %ebp, 0x58(%rbx)
movb $0x1, 0x18(%rbx)
andl $0x0, 0x19(%rbx)
andl $0x0, 0x1c(%rbx)
leaq 0x18(%rbx), %r14
leaq 0x20(%rbx), %rdi
movq 0x18(%rsp), %rsi
decq %rsi
callq 0x68e6
movb $0x22, 0x28(%rbx)
leaq 0x30(%rbx), %rdi
andl $0x0, 0x29(%rbx)
movq 0x30(%rsp), %rsi
addq $-0x22, %rsi
andl $0x0, 0x2c(%rbx)
callq 0x68e6
movabsq $0x8000000080, %rax     # imm = 0x8000000080
movq %rax, 0x50(%rbx)
leaq 0x48(%rbx), %r13
movl $0x2, 0x48(%rbx)
leaq 0x38(%rbx), %rsi
movl 0x10(%rsp), %edi
callq 0xacca
pushq $-0x1
popq %rax
cmpq $0x5c, %r15
je 0xa27e
movzbl (%rbx,%r15), %esi
incq %r15
movl %eax, %edi
callq 0xaca5
jmp 0xa23f
movb $0x8, %cl
movl %r14d, 0xc(%rsp)
testb %cl, %cl
je 0xa2f6
movzbl %cl, %ebp
movl %r12d, %eax
xorl %edx, %edx
divl %ebp
cmpl $0xfc3f, %eax           # imm = 0xFC3F
jb 0xa2fb
addb %cl, %cl
jmp 0xa25d
notl %eax
movl %eax, 0x10(%rbx)
pushq $0x1
popq %rdx
pushq $0x1
popq %r12
movl 0x14(%rsp), %r15d
movl %r15d, %edi
movq %rbx, %rsi
movl %r12d, %ecx
callq 0x28af
testl %eax, %eax
jne 0x9fcd
movq 0x18(%rsp), %rbp
decq %rbp
movq %r14, %rdi
movq %rbp, %rsi
callq 0x68e6
movb $0x1, 0x20(%rbx)
andl $0x0, 0x21(%rbx)
andl $0x0, 0x24(%rbx)
movq %r13, %rdi
movq 0x20(%rsp), %rsi
callq 0x68e6
andl $0x0, 0x10(%rbx)
pushq $-0x1
popq %rax
xorl %r14d, %r14d
cmpq $0x5c, %r14
je 0xa43e
movzbl (%rbx,%r14), %esi
incq %r14
movl %eax, %edi
callq 0xaca5
jmp 0xa2db
movl $0xff, %ebp
xorl %r14d, %r14d
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
xorl %esi, %esi
callq 0x2110
pushq $0x64
popq %rcx
movl %r12d, %eax
xorl %edx, %edx
divl %ecx
movl %eax, %r8d
leaq 0x1cd(%rbx), %rcx
pushq $0x3f
popq %r9
movl $0xc0, %r10d
movl %r9d, %eax
cmpq $0x3, %r14
ja 0xa406
testl %eax, %eax
je 0xa406
movl %r12d, %esi
subl %eax, %esi
jbe 0xa406
movl (%r13,%r14,8), %edi
movl %r8d, %edx
imull %edi, %edx
cmpl $0x64, %edi
cmovel %r12d, %edx
cmoval %edi, %edx
movl %edx, %edi
addl %eax, %edi
cmovbl %esi, %edx
cmpl %r12d, %edi
cmoval %esi, %edx
testl %edx, %edx
je 0xa406
movb %al, -0x7(%rcx)
movb %ah, -0x6(%rcx)
movl %eax, %edi
leal (%rdx,%rax), %r11d
leal (%rdx,%rax), %esi
decl %esi
movl %eax, %r13d
shrl $0x10, %r13d
movb %r13b, -0x5(%rcx)
movq 0x28(%rsp), %r13
shrl $0x18, %edi
movb %dil, -0x4(%rcx)
movb %dl, -0x3(%rcx)
movb %dh, -0x2(%rcx)
movl %edx, %edi
shrl $0x10, %edi
movb %dil, -0x1(%rcx)
shrl $0x18, %edx
movb %dl, (%rcx)
movb %r15b, -0xb(%rcx)
xorl %edx, %edx
divl %r9d
movl %edx, %edi
xorl %edx, %edx
divl %ebp
incl %edi
movb %dl, -0xe(%rcx)
movl %eax, %edx
shrl $0x2, %edx
andl %r10d, %edx
orl %edi, %edx
movb %dl, -0xd(%rcx)
movb %al, -0xc(%rcx)
movl %esi, %eax
xorl %edx, %edx
divl %r9d
movl %edx, %esi
xorl %edx, %edx
divl %ebp
incl %esi
movb %dl, -0xa(%rcx)
movl %eax, %edx
shrl $0x2, %edx
andl %r10d, %edx
orl %esi, %edx
movb %dl, -0x9(%rcx)
movb %al, -0x8(%rcx)
incq %r14
addq $0x10, %rcx
movl %r11d, %eax
jmp 0xa32e
movw $0xaa55, 0x1fe(%rbx)    # imm = 0xAA55
movzbl 0xc(%rsp), %edi
pushq $0x1
popq %r12
movq %rbx, %rsi
xorl %edx, %edx
movl %r12d, %ecx
callq 0x28af
testl %eax, %eax
jne 0x9fcd
xorl %r12d, %r12d
jmp 0x9fcd
pushq $0x1
popq %r12
jmp 0x9fcd
notl %eax
movl %eax, 0x10(%rbx)
pushq $0x1
popq %r12
movl %r15d, %edi
movq %rbx, %rsi
movq %rbp, %rdx
movl %r12d, %ecx
callq 0x28af
testl %eax, %eax
jne 0x9fcd
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
xorl %esi, %esi
callq 0x2110
leaq 0x1be(%rbx), %rdi
leaq 0x1ff3(%rip), %rsi      # 0xc470
pushq $0x10
popq %rdx
callq 0x60c7
movw $0xaa55, 0x1fe(%rbx)    # imm = 0xAA55
pushq $0x1
popq %r12
movl %r15d, %edi
jmp 0xa418