1 /* $NetBSD: v7fs_endian.c,v 1.3 2026/01/06 10:53:10 nia Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #if HAVE_NBTOOL_CONFIG_H 33 #include "nbtool_config.h" 34 #endif 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: v7fs_endian.c,v 1.3 2026/01/06 10:53:10 nia Exp $"); 38 39 #include <sys/endian.h> 40 41 #if defined _KERNEL_OPT 42 #include "opt_v7fs.h" 43 #endif 44 45 #include "v7fs.h" 46 #include "v7fs_endian.h" 47 #include "v7fs_impl.h" 48 49 #ifndef BYTE_ORDER 50 #error 51 #endif 52 53 /* PDP to Little */ 54 #define bswap32pdp_le(x) \ 55 ((uint32_t) \ 56 ((((x) & 0xffff0000) >> 16) | \ 57 (((x) & 0x0000ffff) << 16))) 58 /* PDP to Big */ 59 #define bswap32pdp_be(x) \ 60 ((uint32_t) \ 61 ((((x) & 0xff00ff00) >> 8) | \ 62 (((x) & 0x00ff00ff) << 8))) 63 #ifdef V7FS_EI 64 static uint32_t val32_normal_order(uint32_t); 65 static uint32_t val32_reverse_order(uint32_t); 66 #if BYTE_ORDER == LITTLE_ENDIAN 67 static uint32_t val32_pdp_to_little(uint32_t); 68 #else 69 static uint32_t val32_pdp_to_big(uint32_t); 70 #endif 71 static uint16_t val16_normal_order(uint16_t); 72 static uint16_t val16_reverse_order(uint16_t); 73 static v7fs_daddr_t val24_reverse_order_read(uint8_t *); 74 static void val24_reverse_order_write(v7fs_daddr_t, uint8_t *); 75 static v7fs_daddr_t val24_pdp_read(uint8_t *); 76 static void val24_pdp_write(v7fs_daddr_t, uint8_t *); 77 78 static uint32_t 79 val32_normal_order(uint32_t v) 80 { 81 82 return v; 83 } 84 85 static uint32_t 86 val32_reverse_order(uint32_t v) 87 { 88 89 return bswap32(v); 90 } 91 #if BYTE_ORDER == LITTLE_ENDIAN 92 static uint32_t 93 val32_pdp_to_little(uint32_t v) 94 { 95 96 return bswap32pdp_le(v); 97 } 98 #else 99 static uint32_t 100 val32_pdp_to_big(uint32_t v) 101 { 102 103 return bswap32pdp_be(v); 104 } 105 #endif 106 static uint16_t 107 val16_normal_order(uint16_t v) 108 { 109 110 return v; 111 } 112 113 static uint16_t 114 val16_reverse_order(uint16_t v) 115 { 116 117 return bswap16(v); 118 } 119 120 static v7fs_daddr_t 121 val24_reverse_order_read(uint8_t *a) 122 { 123 #if BYTE_ORDER == LITTLE_ENDIAN 124 return (a[0] << 16) | (a[1] << 8) | a[2]; 125 #else 126 return (a[2] << 16) | (a[1] << 8) | a[0]; 127 #endif 128 } 129 130 static void 131 val24_reverse_order_write(v7fs_daddr_t addr, uint8_t *a) 132 { 133 #if BYTE_ORDER == LITTLE_ENDIAN 134 a[0] = (addr >> 16) & 0xff; 135 a[1] = (addr >> 8) & 0xff; 136 a[2] = addr & 0xff; 137 #else 138 a[0] = addr & 0xff; 139 a[1] = (addr >> 8) & 0xff; 140 a[2] = (addr >> 16) & 0xff; 141 #endif 142 } 143 144 static v7fs_daddr_t 145 val24_pdp_read(uint8_t *a) 146 { 147 148 return (a[0] << 16) | a[1] | (a[2] << 8); 149 } 150 151 static void 152 val24_pdp_write(v7fs_daddr_t addr, uint8_t *a) 153 { 154 155 a[0] = (addr >> 16) & 0xff; 156 a[1] = addr & 0xff; 157 a[2] = (addr >> 8) & 0xff; 158 } 159 160 void 161 v7fs_endian_init(struct v7fs_self *fs) 162 { 163 struct endian_conversion_ops *ops = &fs->val; 164 165 switch (fs->endian) 166 { 167 #if BYTE_ORDER == LITTLE_ENDIAN 168 case LITTLE_ENDIAN: 169 ops->conv32 = val32_normal_order; 170 ops->conv16 = val16_normal_order; 171 ops->conv24read = val24_normal_order_read; 172 ops->conv24write = val24_normal_order_write; 173 break; 174 case BIG_ENDIAN: 175 ops->conv32 = val32_reverse_order; 176 ops->conv16 = val16_reverse_order; 177 ops->conv24read = val24_reverse_order_read; 178 ops->conv24write = val24_reverse_order_write; 179 break; 180 case PDP_ENDIAN: 181 ops->conv32 = val32_pdp_to_little; 182 ops->conv16 = val16_normal_order; 183 ops->conv24read = val24_pdp_read; 184 ops->conv24write = val24_pdp_write; 185 break; 186 #else /* BIG_ENDIAN */ 187 case LITTLE_ENDIAN: 188 ops->conv32 = val32_reverse_order; 189 ops->conv16 = val16_reverse_order; 190 ops->conv24read = val24_reverse_order_read; 191 ops->conv24write = val24_reverse_order_write; 192 break; 193 case BIG_ENDIAN: 194 ops->conv32 = val32_normal_order; 195 ops->conv16 = val16_normal_order; 196 ops->conv24read = val24_normal_order_read; 197 ops->conv24write = val24_normal_order_write; 198 break; 199 case PDP_ENDIAN: 200 ops->conv32 = val32_pdp_to_big; 201 ops->conv16 = val16_reverse_order; 202 ops->conv24read = val24_pdp_read; 203 ops->conv24write = val24_pdp_write; 204 break; 205 #endif 206 } 207 } 208 #endif /* V7FS_EI */ 209 v7fs_daddr_t 210 val24_normal_order_read(uint8_t *a) 211 { 212 /*(v7fs_daddr_t)cast is required for int 16bit system. */ 213 #if BYTE_ORDER == LITTLE_ENDIAN 214 return ((v7fs_daddr_t)a[2] << 16) | ((v7fs_daddr_t)a[1] << 8) | 215 (v7fs_daddr_t)a[0]; 216 #else 217 return ((v7fs_daddr_t)a[0] << 16) | ((v7fs_daddr_t)a[1] << 8) | 218 (v7fs_daddr_t)a[2]; 219 #endif 220 } 221 222 void 223 val24_normal_order_write(v7fs_daddr_t addr, uint8_t *a) 224 { 225 #if BYTE_ORDER == LITTLE_ENDIAN 226 a[0] = addr & 0xff; 227 a[1] = (addr >> 8) & 0xff; 228 a[2] = (addr >> 16) & 0xff; 229 #else 230 a[0] = (addr >> 16) & 0xff; 231 a[1] = (addr >> 8) & 0xff; 232 a[2] = addr & 0xff; 233 #endif 234 } 235