// File: /workspace/github_c_makefile_star2_O2/blasphemy[P]mmc-utils/mmc_cmds.c
// Function: check_enhanced_area_total_limit
int check_enhanced_area_total_limit(const char * const device, int fd)
{
	__u8 ext_csd[512];
	__u32 regl;
	unsigned long max_enh_area_sz, user_area_sz, enh_area_sz = 0;
	unsigned long gp4_part_sz, gp3_part_sz, gp2_part_sz, gp1_part_sz;
	unsigned long total_sz, total_gp_user_sz;
	unsigned int wp_sz, erase_sz;
	int ret;

	ret = read_extcsd(fd, ext_csd);
	if (ret) {
		fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
		exit(1);
	}
	wp_sz = get_hc_wp_grp_size(ext_csd);
	erase_sz = get_hc_erase_grp_size(ext_csd);

	regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_4_2] << 16) |
		(ext_csd[EXT_CSD_GP_SIZE_MULT_4_1] << 8) |
		ext_csd[EXT_CSD_GP_SIZE_MULT_4_0];
	gp4_part_sz = 512l * regl * erase_sz * wp_sz;
	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_4) {
		enh_area_sz += gp4_part_sz;
		printf("Enhanced GP4 Partition Size [GP_SIZE_MULT_4]: 0x%06x\n", regl);
		printf(" i.e. %lu KiB\n", gp4_part_sz);
	}

	regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_3_2] << 16) |
		(ext_csd[EXT_CSD_GP_SIZE_MULT_3_1] << 8) |
		ext_csd[EXT_CSD_GP_SIZE_MULT_3_0];
	gp3_part_sz = 512l * regl * erase_sz * wp_sz;
	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_3) {
		enh_area_sz += gp3_part_sz;
		printf("Enhanced GP3 Partition Size [GP_SIZE_MULT_3]: 0x%06x\n", regl);
		printf(" i.e. %lu KiB\n", gp3_part_sz);
	}

	regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_2_2] << 16) |
		(ext_csd[EXT_CSD_GP_SIZE_MULT_2_1] << 8) |
		ext_csd[EXT_CSD_GP_SIZE_MULT_2_0];
	gp2_part_sz = 512l * regl * erase_sz * wp_sz;
	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_2) {
		enh_area_sz += gp2_part_sz;
		printf("Enhanced GP2 Partition Size [GP_SIZE_MULT_2]: 0x%06x\n", regl);
		printf(" i.e. %lu KiB\n", gp2_part_sz);
	}

	regl = (ext_csd[EXT_CSD_GP_SIZE_MULT_1_2] << 16) |
		(ext_csd[EXT_CSD_GP_SIZE_MULT_1_1] << 8) |
		ext_csd[EXT_CSD_GP_SIZE_MULT_1_0];
	gp1_part_sz = 512l * regl * erase_sz * wp_sz;
	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_1) {
		enh_area_sz += gp1_part_sz;
		printf("Enhanced GP1 Partition Size [GP_SIZE_MULT_1]: 0x%06x\n", regl);
		printf(" i.e. %lu KiB\n", gp1_part_sz);
	}

	regl = (ext_csd[EXT_CSD_ENH_SIZE_MULT_2] << 16) |
		(ext_csd[EXT_CSD_ENH_SIZE_MULT_1] << 8) |
		ext_csd[EXT_CSD_ENH_SIZE_MULT_0];
	user_area_sz = 512l * regl * erase_sz * wp_sz;
	if (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & EXT_CSD_ENH_USR) {
		enh_area_sz += user_area_sz;
		printf("Enhanced User Data Area Size [ENH_SIZE_MULT]: 0x%06x\n", regl);
		printf(" i.e. %lu KiB\n", user_area_sz);
	}

	regl = (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_2] << 16) |
		(ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_1] << 8) |
		ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT_0];
	max_enh_area_sz = 512l * regl * erase_sz * wp_sz;
	printf("Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x%06x\n", regl);
	printf(" i.e. %lu KiB\n", max_enh_area_sz);
	if (enh_area_sz > max_enh_area_sz) {
		fprintf(stderr,
			"Programmed total enhanced size %lu KiB cannot exceed max enhanced area %lu KiB %s\n",
			enh_area_sz, max_enh_area_sz, device);
		return 1;
	}
	total_sz = get_sector_count(ext_csd) / 2;
	total_gp_user_sz = gp4_part_sz + gp3_part_sz + gp2_part_sz +
				gp1_part_sz + user_area_sz;
	if (total_gp_user_sz > total_sz) {
		fprintf(stderr,
			"requested total partition size %lu KiB cannot exceed card capacity %lu KiB %s\n",
			total_gp_user_sz, total_sz, device);
		return 1;
	}

	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x228, %rsp            # imm = 0x228
movl %esi, %eax
movq %rdi, %r15
leaq 0x20(%rsp), %rsi
movl %eax, %edi
callq 0x39b8
testl %eax, %eax
jne 0x4f67
movzbl 0xfd(%rsp), %eax
movzbl 0x100(%rsp), %r14d
imull %eax, %r14d
movzwl 0xb9(%rsp), %eax
shll $0x8, %eax
movzbl 0xb8(%rsp), %edx
orl %eax, %edx
shll $0x9, %r14d
movq %r14, %r12
imulq %rdx, %r12
movb 0xbc(%rsp), %al
testb $0x10, %al
movq %r12, 0x18(%rsp)
jne 0x4d20
xorl %r12d, %r12d
jmp 0x4d4d
leaq 0xa23d(%rip), %rsi      # 0xef64
pushq $0x1
popq %rbx
movl %ebx, %edi
xorl %eax, %eax
callq 0x31d0
leaq 0xa260(%rip), %rsi      # 0xef9a
movl %ebx, %edi
movq %r12, %rdx
xorl %eax, %eax
callq 0x31d0
movb 0xbc(%rsp), %al
movzwl 0xb6(%rsp), %ecx
shll $0x8, %ecx
movzbl 0xb5(%rsp), %edx
orl %ecx, %edx
movq %r14, %r13
imulq %rdx, %r13
testb $0x8, %al
je 0x4d9d
addq %r13, %r12
leaq 0xa232(%rip), %rsi      # 0xefa9
pushq $0x1
popq %rbx
movl %ebx, %edi
xorl %eax, %eax
callq 0x31d0
leaq 0xa210(%rip), %rsi      # 0xef9a
movl %ebx, %edi
movq %r13, %rdx
xorl %eax, %eax
callq 0x31d0
movb 0xbc(%rsp), %al
movzwl 0xb3(%rsp), %ecx
shll $0x8, %ecx
movzbl 0xb2(%rsp), %edx
orl %ecx, %edx
movq %r14, %rbp
imulq %rdx, %rbp
testb $0x4, %al
je 0x4ded
addq %rbp, %r12
leaq 0xa218(%rip), %rsi      # 0xefdf
pushq $0x1
popq %rbx
movl %ebx, %edi
xorl %eax, %eax
callq 0x31d0
leaq 0xa1c0(%rip), %rsi      # 0xef9a
movl %ebx, %edi
movq %rbp, %rdx
xorl %eax, %eax
callq 0x31d0
movb 0xbc(%rsp), %al
movzwl 0xb0(%rsp), %ecx
shll $0x8, %ecx
movzbl 0xaf(%rsp), %edx
orl %ecx, %edx
movq %r14, %rbx
imulq %rdx, %rbx
testb $0x2, %al
movq %r15, (%rsp)
je 0x4e44
addq %rbx, %r12
leaq 0xa1fa(%rip), %rsi      # 0xf015
pushq $0x1
popq %r15
movl %r15d, %edi
xorl %eax, %eax
callq 0x31d0
leaq 0xa16a(%rip), %rsi      # 0xef9a
movl %r15d, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x31d0
movb 0xbc(%rsp), %al
movq %rbx, 0x8(%rsp)
movzwl 0xad(%rsp), %ecx
shll $0x8, %ecx
movzbl 0xac(%rsp), %edx
orl %ecx, %edx
movq %r14, %r15
imulq %rdx, %r15
testb $0x1, %al
movq %r13, 0x10(%rsp)
je 0x4e9a
addq %r15, %r12
leaq 0xa1d3(%rip), %rsi      # 0xf04b
pushq $0x1
popq %r13
movl %r13d, %edi
xorl %eax, %eax
callq 0x31d0
leaq 0xa10d(%rip), %rsi      # 0xef9a
movl %r13d, %edi
movq %r15, %rdx
xorl %eax, %eax
callq 0x31d0
movq %r12, %rbx
movzwl 0xbe(%rsp), %eax
shll $0x8, %eax
movzbl 0xbd(%rsp), %edx
orl %eax, %edx
imulq %rdx, %r14
leaq 0xa1c4(%rip), %rsi      # 0xf081
xorl %r13d, %r13d
pushq $0x1
popq %r12
movl %r12d, %edi
xorl %eax, %eax
callq 0x31d0
leaq 0xa0c5(%rip), %rsi      # 0xef9a
movl %r12d, %edi
movq %r14, %rdx
xorl %eax, %eax
callq 0x31d0
cmpq %r14, %rbx
jbe 0x4f07
movq 0x13102(%rip), %rax     # 0x17ff0
movq (%rax), %rdi
leaq 0xa1bd(%rip), %rdx      # 0xf0b5
pushq $0x1
popq %r13
movl %r13d, %esi
movq %rbx, %rcx
movq %r14, %r8
jmp 0x4f47
movl 0xf4(%rsp), %r8d
shrl %r8d
movq 0x10(%rsp), %rax
addq 0x18(%rsp), %rax
addq 0x8(%rsp), %rbp
addq %rax, %rbp
addq %r15, %rbp
cmpq %r8, %rbp
jbe 0x4f52
movq 0x130bd(%rip), %rax     # 0x17ff0
movq (%rax), %rdi
leaq 0xa1cb(%rip), %rdx      # 0xf108
pushq $0x1
popq %r13
movl %r13d, %esi
movq %rbp, %rcx
movq (%rsp), %r9
xorl %eax, %eax
callq 0x3250
movl %r13d, %eax
addq $0x228, %rsp            # imm = 0x228
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x13082(%rip), %rax     # 0x17ff0
movq (%rax), %rdi
leaq 0x978d(%rip), %rdx      # 0xe705
pushq $0x1
popq %rbx
movl %ebx, %esi
movq %r15, %rcx
xorl %eax, %eax
callq 0x3250
movl %ebx, %edi
callq 0x3230