162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/types.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "ntfs_fs.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define BITS_IN_SIZE_T (sizeof(size_t) * 8)
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/*
1562306a36Sopenharmony_ci * fill_mask[i] - first i bits are '1' , i = 0,1,2,3,4,5,6,7,8
1662306a36Sopenharmony_ci * fill_mask[i] = 0xFF >> (8-i)
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_cistatic const u8 fill_mask[] = { 0x00, 0x01, 0x03, 0x07, 0x0F,
1962306a36Sopenharmony_ci				0x1F, 0x3F, 0x7F, 0xFF };
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci * zero_mask[i] - first i bits are '0' , i = 0,1,2,3,4,5,6,7,8
2362306a36Sopenharmony_ci * zero_mask[i] = 0xFF << i
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_cistatic const u8 zero_mask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
2662306a36Sopenharmony_ci				0xE0, 0xC0, 0x80, 0x00 };
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * are_bits_clear
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * Return: True if all bits [bit, bit+nbits) are zeros "0".
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_cibool are_bits_clear(const void *lmap, size_t bit, size_t nbits)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	size_t pos = bit & 7;
3662306a36Sopenharmony_ci	const u8 *map = (u8 *)lmap + (bit >> 3);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (pos) {
3962306a36Sopenharmony_ci		if (8 - pos >= nbits)
4062306a36Sopenharmony_ci			return !nbits || !(*map & fill_mask[pos + nbits] &
4162306a36Sopenharmony_ci					   zero_mask[pos]);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci		if (*map++ & zero_mask[pos])
4462306a36Sopenharmony_ci			return false;
4562306a36Sopenharmony_ci		nbits -= 8 - pos;
4662306a36Sopenharmony_ci	}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	pos = ((size_t)map) & (sizeof(size_t) - 1);
4962306a36Sopenharmony_ci	if (pos) {
5062306a36Sopenharmony_ci		pos = sizeof(size_t) - pos;
5162306a36Sopenharmony_ci		if (nbits >= pos * 8) {
5262306a36Sopenharmony_ci			for (nbits -= pos * 8; pos; pos--, map++) {
5362306a36Sopenharmony_ci				if (*map)
5462306a36Sopenharmony_ci					return false;
5562306a36Sopenharmony_ci			}
5662306a36Sopenharmony_ci		}
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	for (pos = nbits / BITS_IN_SIZE_T; pos; pos--, map += sizeof(size_t)) {
6062306a36Sopenharmony_ci		if (*((size_t *)map))
6162306a36Sopenharmony_ci			return false;
6262306a36Sopenharmony_ci	}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	for (pos = (nbits % BITS_IN_SIZE_T) >> 3; pos; pos--, map++) {
6562306a36Sopenharmony_ci		if (*map)
6662306a36Sopenharmony_ci			return false;
6762306a36Sopenharmony_ci	}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	pos = nbits & 7;
7062306a36Sopenharmony_ci	if (pos && (*map & fill_mask[pos]))
7162306a36Sopenharmony_ci		return false;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	return true;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci/*
7762306a36Sopenharmony_ci * are_bits_set
7862306a36Sopenharmony_ci *
7962306a36Sopenharmony_ci * Return: True if all bits [bit, bit+nbits) are ones "1".
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_cibool are_bits_set(const void *lmap, size_t bit, size_t nbits)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	u8 mask;
8462306a36Sopenharmony_ci	size_t pos = bit & 7;
8562306a36Sopenharmony_ci	const u8 *map = (u8 *)lmap + (bit >> 3);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	if (pos) {
8862306a36Sopenharmony_ci		if (8 - pos >= nbits) {
8962306a36Sopenharmony_ci			mask = fill_mask[pos + nbits] & zero_mask[pos];
9062306a36Sopenharmony_ci			return !nbits || (*map & mask) == mask;
9162306a36Sopenharmony_ci		}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci		mask = zero_mask[pos];
9462306a36Sopenharmony_ci		if ((*map++ & mask) != mask)
9562306a36Sopenharmony_ci			return false;
9662306a36Sopenharmony_ci		nbits -= 8 - pos;
9762306a36Sopenharmony_ci	}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	pos = ((size_t)map) & (sizeof(size_t) - 1);
10062306a36Sopenharmony_ci	if (pos) {
10162306a36Sopenharmony_ci		pos = sizeof(size_t) - pos;
10262306a36Sopenharmony_ci		if (nbits >= pos * 8) {
10362306a36Sopenharmony_ci			for (nbits -= pos * 8; pos; pos--, map++) {
10462306a36Sopenharmony_ci				if (*map != 0xFF)
10562306a36Sopenharmony_ci					return false;
10662306a36Sopenharmony_ci			}
10762306a36Sopenharmony_ci		}
10862306a36Sopenharmony_ci	}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	for (pos = nbits / BITS_IN_SIZE_T; pos; pos--, map += sizeof(size_t)) {
11162306a36Sopenharmony_ci		if (*((size_t *)map) != MINUS_ONE_T)
11262306a36Sopenharmony_ci			return false;
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	for (pos = (nbits % BITS_IN_SIZE_T) >> 3; pos; pos--, map++) {
11662306a36Sopenharmony_ci		if (*map != 0xFF)
11762306a36Sopenharmony_ci			return false;
11862306a36Sopenharmony_ci	}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	pos = nbits & 7;
12162306a36Sopenharmony_ci	if (pos) {
12262306a36Sopenharmony_ci		mask = fill_mask[pos];
12362306a36Sopenharmony_ci		if ((*map & mask) != mask)
12462306a36Sopenharmony_ci			return false;
12562306a36Sopenharmony_ci	}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return true;
12862306a36Sopenharmony_ci}
129