cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

regulatory.rst (7401B)


      1.. SPDX-License-Identifier: GPL-2.0
      2
      3=======================================
      4Linux wireless regulatory documentation
      5=======================================
      6
      7This document gives a brief review over how the Linux wireless
      8regulatory infrastructure works.
      9
     10More up to date information can be obtained at the project's web page:
     11
     12https://wireless.wiki.kernel.org/en/developers/Regulatory
     13
     14Keeping regulatory domains in userspace
     15---------------------------------------
     16
     17Due to the dynamic nature of regulatory domains we keep them
     18in userspace and provide a framework for userspace to upload
     19to the kernel one regulatory domain to be used as the central
     20core regulatory domain all wireless devices should adhere to.
     21
     22How to get regulatory domains to the kernel
     23-------------------------------------------
     24
     25When the regulatory domain is first set up, the kernel will request a
     26database file (regulatory.db) containing all the regulatory rules. It
     27will then use that database when it needs to look up the rules for a
     28given country.
     29
     30How to get regulatory domains to the kernel (old CRDA solution)
     31---------------------------------------------------------------
     32
     33Userspace gets a regulatory domain in the kernel by having
     34a userspace agent build it and send it via nl80211. Only
     35expected regulatory domains will be respected by the kernel.
     36
     37A currently available userspace agent which can accomplish this
     38is CRDA - central regulatory domain agent. Its documented here:
     39
     40https://wireless.wiki.kernel.org/en/developers/Regulatory/CRDA
     41
     42Essentially the kernel will send a udev event when it knows
     43it needs a new regulatory domain. A udev rule can be put in place
     44to trigger crda to send the respective regulatory domain for a
     45specific ISO/IEC 3166 alpha2.
     46
     47Below is an example udev rule which can be used:
     48
     49# Example file, should be put in /etc/udev/rules.d/regulatory.rules
     50KERNEL=="regulatory*", ACTION=="change", SUBSYSTEM=="platform", RUN+="/sbin/crda"
     51
     52The alpha2 is passed as an environment variable under the variable COUNTRY.
     53
     54Who asks for regulatory domains?
     55--------------------------------
     56
     57* Users
     58
     59Users can use iw:
     60
     61https://wireless.wiki.kernel.org/en/users/Documentation/iw
     62
     63An example::
     64
     65  # set regulatory domain to "Costa Rica"
     66  iw reg set CR
     67
     68This will request the kernel to set the regulatory domain to
     69the specificied alpha2. The kernel in turn will then ask userspace
     70to provide a regulatory domain for the alpha2 specified by the user
     71by sending a uevent.
     72
     73* Wireless subsystems for Country Information elements
     74
     75The kernel will send a uevent to inform userspace a new
     76regulatory domain is required. More on this to be added
     77as its integration is added.
     78
     79* Drivers
     80
     81If drivers determine they need a specific regulatory domain
     82set they can inform the wireless core using regulatory_hint().
     83They have two options -- they either provide an alpha2 so that
     84crda can provide back a regulatory domain for that country or
     85they can build their own regulatory domain based on internal
     86custom knowledge so the wireless core can respect it.
     87
     88*Most* drivers will rely on the first mechanism of providing a
     89regulatory hint with an alpha2. For these drivers there is an additional
     90check that can be used to ensure compliance based on custom EEPROM
     91regulatory data. This additional check can be used by drivers by
     92registering on its struct wiphy a reg_notifier() callback. This notifier
     93is called when the core's regulatory domain has been changed. The driver
     94can use this to review the changes made and also review who made them
     95(driver, user, country IE) and determine what to allow based on its
     96internal EEPROM data. Devices drivers wishing to be capable of world
     97roaming should use this callback. More on world roaming will be
     98added to this document when its support is enabled.
     99
    100Device drivers who provide their own built regulatory domain
    101do not need a callback as the channels registered by them are
    102the only ones that will be allowed and therefore *additional*
    103channels cannot be enabled.
    104
    105Example code - drivers hinting an alpha2:
    106------------------------------------------
    107
    108This example comes from the zd1211rw device driver. You can start
    109by having a mapping of your device's EEPROM country/regulatory
    110domain value to a specific alpha2 as follows::
    111
    112  static struct zd_reg_alpha2_map reg_alpha2_map[] = {
    113	{ ZD_REGDOMAIN_FCC, "US" },
    114	{ ZD_REGDOMAIN_IC, "CA" },
    115	{ ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
    116	{ ZD_REGDOMAIN_JAPAN, "JP" },
    117	{ ZD_REGDOMAIN_JAPAN_ADD, "JP" },
    118	{ ZD_REGDOMAIN_SPAIN, "ES" },
    119	{ ZD_REGDOMAIN_FRANCE, "FR" },
    120
    121Then you can define a routine to map your read EEPROM value to an alpha2,
    122as follows::
    123
    124  static int zd_reg2alpha2(u8 regdomain, char *alpha2)
    125  {
    126	unsigned int i;
    127	struct zd_reg_alpha2_map *reg_map;
    128		for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
    129			reg_map = &reg_alpha2_map[i];
    130			if (regdomain == reg_map->reg) {
    131			alpha2[0] = reg_map->alpha2[0];
    132			alpha2[1] = reg_map->alpha2[1];
    133			return 0;
    134		}
    135	}
    136	return 1;
    137  }
    138
    139Lastly, you can then hint to the core of your discovered alpha2, if a match
    140was found. You need to do this after you have registered your wiphy. You
    141are expected to do this during initialization.
    142
    143::
    144
    145	r = zd_reg2alpha2(mac->regdomain, alpha2);
    146	if (!r)
    147		regulatory_hint(hw->wiphy, alpha2);
    148
    149Example code - drivers providing a built in regulatory domain:
    150--------------------------------------------------------------
    151
    152[NOTE: This API is not currently available, it can be added when required]
    153
    154If you have regulatory information you can obtain from your
    155driver and you *need* to use this we let you build a regulatory domain
    156structure and pass it to the wireless core. To do this you should
    157kmalloc() a structure big enough to hold your regulatory domain
    158structure and you should then fill it with your data. Finally you simply
    159call regulatory_hint() with the regulatory domain structure in it.
    160
    161Bellow is a simple example, with a regulatory domain cached using the stack.
    162Your implementation may vary (read EEPROM cache instead, for example).
    163
    164Example cache of some regulatory domain::
    165
    166  struct ieee80211_regdomain mydriver_jp_regdom = {
    167	.n_reg_rules = 3,
    168	.alpha2 =  "JP",
    169	//.alpha2 =  "99", /* If I have no alpha2 to map it to */
    170	.reg_rules = {
    171		/* IEEE 802.11b/g, channels 1..14 */
    172		REG_RULE(2412-10, 2484+10, 40, 6, 20, 0),
    173		/* IEEE 802.11a, channels 34..48 */
    174		REG_RULE(5170-10, 5240+10, 40, 6, 20,
    175			NL80211_RRF_NO_IR),
    176		/* IEEE 802.11a, channels 52..64 */
    177		REG_RULE(5260-10, 5320+10, 40, 6, 20,
    178			NL80211_RRF_NO_IR|
    179			NL80211_RRF_DFS),
    180	}
    181  };
    182
    183Then in some part of your code after your wiphy has been registered::
    184
    185	struct ieee80211_regdomain *rd;
    186	int size_of_regd;
    187	int num_rules = mydriver_jp_regdom.n_reg_rules;
    188	unsigned int i;
    189
    190	size_of_regd = sizeof(struct ieee80211_regdomain) +
    191		(num_rules * sizeof(struct ieee80211_reg_rule));
    192
    193	rd = kzalloc(size_of_regd, GFP_KERNEL);
    194	if (!rd)
    195		return -ENOMEM;
    196
    197	memcpy(rd, &mydriver_jp_regdom, sizeof(struct ieee80211_regdomain));
    198
    199	for (i=0; i < num_rules; i++)
    200		memcpy(&rd->reg_rules[i],
    201		       &mydriver_jp_regdom.reg_rules[i],
    202		       sizeof(struct ieee80211_reg_rule));
    203	regulatory_struct_hint(rd);
    204
    205Statically compiled regulatory database
    206---------------------------------------
    207
    208When a database should be fixed into the kernel, it can be provided as a
    209firmware file at build time that is then linked into the kernel.