0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <linux/hw_random.h>
0028 #include <linux/io.h>
0029 #include <linux/kernel.h>
0030 #include <linux/module.h>
0031 #include <linux/pci.h>
0032 #include <linux/stop_machine.h>
0033 #include <linux/delay.h>
0034 #include <linux/slab.h>
0035
0036
0037 #define PFX KBUILD_MODNAME ": "
0038
0039
0040
0041
0042 #define INTEL_RNG_HW_STATUS 0
0043 #define INTEL_RNG_PRESENT 0x40
0044 #define INTEL_RNG_ENABLED 0x01
0045 #define INTEL_RNG_STATUS 1
0046 #define INTEL_RNG_DATA_PRESENT 0x01
0047 #define INTEL_RNG_DATA 2
0048
0049
0050
0051
0052 #define INTEL_RNG_ADDR 0xFFBC015F
0053 #define INTEL_RNG_ADDR_LEN 3
0054
0055
0056
0057
0058 #define FWH_DEC_EN1_REG_OLD 0xe3
0059 #define FWH_DEC_EN1_REG_NEW 0xd9
0060 #define FWH_F8_EN_MASK 0x80
0061
0062 #define BIOS_CNTL_REG_OLD 0x4e
0063 #define BIOS_CNTL_REG_NEW 0xdc
0064 #define BIOS_CNTL_WRITE_ENABLE_MASK 0x01
0065 #define BIOS_CNTL_LOCK_ENABLE_MASK 0x02
0066
0067
0068
0069
0070 #define INTEL_FWH_ADDR 0xffff0000
0071 #define INTEL_FWH_ADDR_LEN 2
0072
0073
0074
0075
0076 #define INTEL_FWH_RESET_CMD 0xff
0077 #define INTEL_FWH_READ_ID_CMD 0x90
0078
0079
0080
0081
0082 #define INTEL_FWH_MANUFACTURER_CODE_ADDRESS 0x000000
0083 #define INTEL_FWH_DEVICE_CODE_ADDRESS 0x000001
0084
0085
0086
0087
0088 #define INTEL_FWH_MANUFACTURER_CODE 0x89
0089 #define INTEL_FWH_DEVICE_CODE_8M 0xac
0090 #define INTEL_FWH_DEVICE_CODE_4M 0xad
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100 static const struct pci_device_id pci_tbl[] = {
0101
0102
0103 { PCI_DEVICE(0x8086, 0x2410) },
0104
0105
0106 { PCI_DEVICE(0x8086, 0x2420) },
0107
0108
0109
0110
0111 { PCI_DEVICE(0x8086, 0x244c) },
0112 { PCI_DEVICE(0x8086, 0x248c) },
0113 { PCI_DEVICE(0x8086, 0x24cc) },
0114 { PCI_DEVICE(0x8086, 0x2641) },
0115 { PCI_DEVICE(0x8086, 0x27b9) },
0116 { PCI_DEVICE(0x8086, 0x27bd) },
0117
0118
0119 { PCI_DEVICE(0x8086, 0x2440) },
0120 { PCI_DEVICE(0x8086, 0x2480) },
0121 { PCI_DEVICE(0x8086, 0x24c0) },
0122 { PCI_DEVICE(0x8086, 0x24d0) },
0123 { PCI_DEVICE(0x8086, 0x25a1) },
0124 { PCI_DEVICE(0x8086, 0x2640) },
0125 { PCI_DEVICE(0x8086, 0x2670) },
0126 { PCI_DEVICE(0x8086, 0x2671) },
0127 { PCI_DEVICE(0x8086, 0x2672) },
0128 { PCI_DEVICE(0x8086, 0x2673) },
0129 { PCI_DEVICE(0x8086, 0x2674) },
0130 { PCI_DEVICE(0x8086, 0x2675) },
0131 { PCI_DEVICE(0x8086, 0x2676) },
0132 { PCI_DEVICE(0x8086, 0x2677) },
0133 { PCI_DEVICE(0x8086, 0x2678) },
0134 { PCI_DEVICE(0x8086, 0x2679) },
0135 { PCI_DEVICE(0x8086, 0x267a) },
0136 { PCI_DEVICE(0x8086, 0x267b) },
0137 { PCI_DEVICE(0x8086, 0x267c) },
0138 { PCI_DEVICE(0x8086, 0x267d) },
0139 { PCI_DEVICE(0x8086, 0x267e) },
0140 { PCI_DEVICE(0x8086, 0x267f) },
0141 { PCI_DEVICE(0x8086, 0x27b8) },
0142
0143
0144 { PCI_DEVICE(0x8086, 0x2450) },
0145 { 0, },
0146 };
0147 MODULE_DEVICE_TABLE(pci, pci_tbl);
0148
0149 static __initdata int no_fwh_detect;
0150 module_param(no_fwh_detect, int, 0);
0151 MODULE_PARM_DESC(no_fwh_detect, "Skip FWH detection:\n"
0152 " positive value - skip if FWH space locked read-only\n"
0153 " negative value - skip always");
0154
0155 static inline u8 hwstatus_get(void __iomem *mem)
0156 {
0157 return readb(mem + INTEL_RNG_HW_STATUS);
0158 }
0159
0160 static inline u8 hwstatus_set(void __iomem *mem,
0161 u8 hw_status)
0162 {
0163 writeb(hw_status, mem + INTEL_RNG_HW_STATUS);
0164 return hwstatus_get(mem);
0165 }
0166
0167 static int intel_rng_data_present(struct hwrng *rng, int wait)
0168 {
0169 void __iomem *mem = (void __iomem *)rng->priv;
0170 int data, i;
0171
0172 for (i = 0; i < 20; i++) {
0173 data = !!(readb(mem + INTEL_RNG_STATUS) &
0174 INTEL_RNG_DATA_PRESENT);
0175 if (data || !wait)
0176 break;
0177 udelay(10);
0178 }
0179 return data;
0180 }
0181
0182 static int intel_rng_data_read(struct hwrng *rng, u32 *data)
0183 {
0184 void __iomem *mem = (void __iomem *)rng->priv;
0185
0186 *data = readb(mem + INTEL_RNG_DATA);
0187
0188 return 1;
0189 }
0190
0191 static int intel_rng_init(struct hwrng *rng)
0192 {
0193 void __iomem *mem = (void __iomem *)rng->priv;
0194 u8 hw_status;
0195 int err = -EIO;
0196
0197 hw_status = hwstatus_get(mem);
0198
0199 if ((hw_status & INTEL_RNG_ENABLED) == 0)
0200 hw_status = hwstatus_set(mem, hw_status | INTEL_RNG_ENABLED);
0201 if ((hw_status & INTEL_RNG_ENABLED) == 0) {
0202 pr_err(PFX "cannot enable RNG, aborting\n");
0203 goto out;
0204 }
0205 err = 0;
0206 out:
0207 return err;
0208 }
0209
0210 static void intel_rng_cleanup(struct hwrng *rng)
0211 {
0212 void __iomem *mem = (void __iomem *)rng->priv;
0213 u8 hw_status;
0214
0215 hw_status = hwstatus_get(mem);
0216 if (hw_status & INTEL_RNG_ENABLED)
0217 hwstatus_set(mem, hw_status & ~INTEL_RNG_ENABLED);
0218 else
0219 pr_warn(PFX "unusual: RNG already disabled\n");
0220 }
0221
0222
0223 static struct hwrng intel_rng = {
0224 .name = "intel",
0225 .init = intel_rng_init,
0226 .cleanup = intel_rng_cleanup,
0227 .data_present = intel_rng_data_present,
0228 .data_read = intel_rng_data_read,
0229 };
0230
0231 struct intel_rng_hw {
0232 struct pci_dev *dev;
0233 void __iomem *mem;
0234 u8 bios_cntl_off;
0235 u8 bios_cntl_val;
0236 u8 fwh_dec_en1_off;
0237 u8 fwh_dec_en1_val;
0238 };
0239
0240 static int __init intel_rng_hw_init(void *_intel_rng_hw)
0241 {
0242 struct intel_rng_hw *intel_rng_hw = _intel_rng_hw;
0243 u8 mfc, dvc;
0244
0245
0246
0247 if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK))
0248 pci_write_config_byte(intel_rng_hw->dev,
0249 intel_rng_hw->fwh_dec_en1_off,
0250 intel_rng_hw->fwh_dec_en1_val |
0251 FWH_F8_EN_MASK);
0252 if (!(intel_rng_hw->bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK))
0253 pci_write_config_byte(intel_rng_hw->dev,
0254 intel_rng_hw->bios_cntl_off,
0255 intel_rng_hw->bios_cntl_val |
0256 BIOS_CNTL_WRITE_ENABLE_MASK);
0257
0258 writeb(INTEL_FWH_RESET_CMD, intel_rng_hw->mem);
0259 writeb(INTEL_FWH_READ_ID_CMD, intel_rng_hw->mem);
0260 mfc = readb(intel_rng_hw->mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS);
0261 dvc = readb(intel_rng_hw->mem + INTEL_FWH_DEVICE_CODE_ADDRESS);
0262 writeb(INTEL_FWH_RESET_CMD, intel_rng_hw->mem);
0263
0264 if (!(intel_rng_hw->bios_cntl_val &
0265 (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
0266 pci_write_config_byte(intel_rng_hw->dev,
0267 intel_rng_hw->bios_cntl_off,
0268 intel_rng_hw->bios_cntl_val);
0269 if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK))
0270 pci_write_config_byte(intel_rng_hw->dev,
0271 intel_rng_hw->fwh_dec_en1_off,
0272 intel_rng_hw->fwh_dec_en1_val);
0273
0274 if (mfc != INTEL_FWH_MANUFACTURER_CODE ||
0275 (dvc != INTEL_FWH_DEVICE_CODE_8M &&
0276 dvc != INTEL_FWH_DEVICE_CODE_4M)) {
0277 pr_notice(PFX "FWH not detected\n");
0278 return -ENODEV;
0279 }
0280
0281 return 0;
0282 }
0283
0284 static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw,
0285 struct pci_dev *dev)
0286 {
0287 intel_rng_hw->bios_cntl_val = 0xff;
0288 intel_rng_hw->fwh_dec_en1_val = 0xff;
0289 intel_rng_hw->dev = dev;
0290
0291
0292 if (dev->device < 0x2640) {
0293 intel_rng_hw->fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
0294 intel_rng_hw->bios_cntl_off = BIOS_CNTL_REG_OLD;
0295 } else {
0296 intel_rng_hw->fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW;
0297 intel_rng_hw->bios_cntl_off = BIOS_CNTL_REG_NEW;
0298 }
0299
0300 pci_read_config_byte(dev, intel_rng_hw->fwh_dec_en1_off,
0301 &intel_rng_hw->fwh_dec_en1_val);
0302 pci_read_config_byte(dev, intel_rng_hw->bios_cntl_off,
0303 &intel_rng_hw->bios_cntl_val);
0304
0305 if ((intel_rng_hw->bios_cntl_val &
0306 (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
0307 == BIOS_CNTL_LOCK_ENABLE_MASK) {
0308 static __initdata char warning[] =
0309 PFX "Firmware space is locked read-only. If you can't or\n"
0310 PFX "don't want to disable this in firmware setup, and if\n"
0311 PFX "you are certain that your system has a functional\n"
0312 PFX "RNG, try using the 'no_fwh_detect' option.\n";
0313
0314 if (no_fwh_detect)
0315 return -ENODEV;
0316 pr_warn("%s", warning);
0317 return -EBUSY;
0318 }
0319
0320 intel_rng_hw->mem = ioremap(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
0321 if (intel_rng_hw->mem == NULL)
0322 return -EBUSY;
0323
0324 return 0;
0325 }
0326
0327
0328 static int __init intel_rng_mod_init(void)
0329 {
0330 int err = -ENODEV;
0331 int i;
0332 struct pci_dev *dev = NULL;
0333 void __iomem *mem;
0334 u8 hw_status;
0335 struct intel_rng_hw *intel_rng_hw;
0336
0337 for (i = 0; !dev && pci_tbl[i].vendor; ++i)
0338 dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device,
0339 NULL);
0340
0341 if (!dev)
0342 goto out;
0343
0344 if (no_fwh_detect < 0) {
0345 pci_dev_put(dev);
0346 goto fwh_done;
0347 }
0348
0349 intel_rng_hw = kmalloc(sizeof(*intel_rng_hw), GFP_KERNEL);
0350 if (!intel_rng_hw) {
0351 pci_dev_put(dev);
0352 goto out;
0353 }
0354
0355 err = intel_init_hw_struct(intel_rng_hw, dev);
0356 if (err) {
0357 pci_dev_put(dev);
0358 kfree(intel_rng_hw);
0359 if (err == -ENODEV)
0360 goto fwh_done;
0361 goto out;
0362 }
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372 err = stop_machine(intel_rng_hw_init, intel_rng_hw, NULL);
0373 pci_dev_put(dev);
0374 iounmap(intel_rng_hw->mem);
0375 kfree(intel_rng_hw);
0376 if (err)
0377 goto out;
0378
0379 fwh_done:
0380 err = -ENOMEM;
0381 mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
0382 if (!mem)
0383 goto out;
0384 intel_rng.priv = (unsigned long)mem;
0385
0386
0387 err = -ENODEV;
0388 hw_status = hwstatus_get(mem);
0389 if ((hw_status & INTEL_RNG_PRESENT) == 0) {
0390 iounmap(mem);
0391 goto out;
0392 }
0393
0394 pr_info("Intel 82802 RNG detected\n");
0395 err = hwrng_register(&intel_rng);
0396 if (err) {
0397 pr_err(PFX "RNG registering failed (%d)\n",
0398 err);
0399 iounmap(mem);
0400 }
0401 out:
0402 return err;
0403
0404 }
0405
0406 static void __exit intel_rng_mod_exit(void)
0407 {
0408 void __iomem *mem = (void __iomem *)intel_rng.priv;
0409
0410 hwrng_unregister(&intel_rng);
0411 iounmap(mem);
0412 }
0413
0414 module_init(intel_rng_mod_init);
0415 module_exit(intel_rng_mod_exit);
0416
0417 MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets");
0418 MODULE_LICENSE("GPL");