iPXE
ath_regd.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
5 * Original from Linux kernel 3.0.1
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20FILE_SECBOOT ( FORBIDDEN );
21
22#include "regd.h"
23#include "regd_common.h"
24
25/*
26 * This is a set of common rules used by our world regulatory domains.
27 * We have 12 world regulatory domains. To save space we consolidate
28 * the regulatory domains in 5 structures by frequency and change
29 * the flags on our reg_notifier() on a case by case basis.
30 */
31
32/* Only these channels all allow active scan on all world regulatory domains */
33#define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
34
35/* We enable active scan on these a case by case basis by regulatory domain */
36#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\
37 NL80211_RRF_PASSIVE_SCAN)
38#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\
39 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
40
41/* We allow IBSS on these on a case by case basis by regulatory domain */
42#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 40, 0, 30,\
43 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
44#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\
45 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
46#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 40, 0, 30,\
47 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
48
49#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \
50 ATH9K_2GHZ_CH12_13, \
51 ATH9K_2GHZ_CH14
52
53#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \
54 ATH9K_5GHZ_5470_5850
55
56/* This one skips what we call "mid band" */
57#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
58 ATH9K_5GHZ_5725_5850
59
60///* Can be used for:
61// * 0x60, 0x61, 0x62 */
62//static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
63// .n_reg_rules = 5,
64// .alpha2 = "99",
65// .reg_rules = {
66// ATH9K_2GHZ_ALL,
67// ATH9K_5GHZ_ALL,
68// }
69//};
70//
71///* Can be used by 0x63 and 0x65 */
72//static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
73// .n_reg_rules = 4,
74// .alpha2 = "99",
75// .reg_rules = {
76// ATH9K_2GHZ_CH01_11,
77// ATH9K_2GHZ_CH12_13,
78// ATH9K_5GHZ_NO_MIDBAND,
79// }
80//};
81//
82///* Can be used by 0x64 only */
83//static const struct ieee80211_regdomain ath_world_regdom_64 = {
84// .n_reg_rules = 3,
85// .alpha2 = "99",
86// .reg_rules = {
87// ATH9K_2GHZ_CH01_11,
88// ATH9K_5GHZ_NO_MIDBAND,
89// }
90//};
91//
92///* Can be used by 0x66 and 0x69 */
93//static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
94// .n_reg_rules = 3,
95// .alpha2 = "99",
96// .reg_rules = {
97// ATH9K_2GHZ_CH01_11,
98// ATH9K_5GHZ_ALL,
99// }
100//};
101//
102///* Can be used by 0x67, 0x68, 0x6A and 0x6C */
103//static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
104// .n_reg_rules = 4,
105// .alpha2 = "99",
106// .reg_rules = {
107// ATH9K_2GHZ_CH01_11,
108// ATH9K_2GHZ_CH12_13,
109// ATH9K_5GHZ_ALL,
110// }
111//};
112//
113//static inline int is_wwr_sku(u16 regd)
114//{
115// return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) &&
116// (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
117// (regd == WORLD));
118//}
119//
120//static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
121//{
122// return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
123//}
124//
125//int ath_is_world_regd(struct ath_regulatory *reg)
126//{
127// return is_wwr_sku(ath_regd_get_eepromRD(reg));
128//}
129//
130//static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
131//{
132// /* this is the most restrictive */
133// return &ath_world_regdom_64;
134//}
135//
136//static const struct
137//ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
138//{
139// switch (reg->regpair->regDmnEnum) {
140// case 0x60:
141// case 0x61:
142// case 0x62:
143// return &ath_world_regdom_60_61_62;
144// case 0x63:
145// case 0x65:
146// return &ath_world_regdom_63_65;
147// case 0x64:
148// return &ath_world_regdom_64;
149// case 0x66:
150// case 0x69:
151// return &ath_world_regdom_66_69;
152// case 0x67:
153// case 0x68:
154// case 0x6A:
155// case 0x6C:
156// return &ath_world_regdom_67_68_6A_6C;
157// default:
158// WARN_ON(1);
159// return ath_default_world_regdomain();
160// }
161//}
162//
163//int ath_is_49ghz_allowed(u16 regdomain)
164//{
165// /* possibly more */
166// return regdomain == MKK9_MKKC;
167//}
168//
169///* Frequency is one where radar detection is required */
170//static int ath_is_radar_freq(u16 center_freq)
171//{
172// return (center_freq >= 5260 && center_freq <= 5700);
173//}
174//
175///*
176// * N.B: These exception rules do not apply radar freqs.
177// *
178// * - We enable adhoc (or beaconing) if allowed by 11d
179// * - We enable active scan if the channel is allowed by 11d
180// * - If no country IE has been processed and a we determine we have
181// * received a beacon on a channel we can enable active scan and
182// * adhoc (or beaconing).
183// */
184//static void
185//ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
186// enum nl80211_reg_initiator initiator)
187//{
188// int band;
189// struct ieee80211_supported_band *sband;
190// const struct ieee80211_reg_rule *reg_rule;
191// struct net80211_channel *ch;
192// unsigned int i;
193// u32 bandwidth = 0;
194// int r;
195//
196// for (band = 0; band < NET80211_NR_BANDS; band++) {
197//
198// if (!wiphy->bands[band])
199// continue;
200//
201// sband = wiphy->bands[band];
202//
203// for (i = 0; i < sband->n_channels; i++) {
204//
205// ch = &sband->channels[i];
206//
207// if (ath_is_radar_freq(ch->center_freq) ||
208// (ch->flags & IEEE80211_CHAN_RADAR))
209// continue;
210//
211// if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
212// r = freq_reg_info(wiphy,
213// ch->center_freq,
214// bandwidth,
215// &reg_rule);
216// if (r)
217// continue;
218// /*
219// * If 11d had a rule for this channel ensure
220// * we enable adhoc/beaconing if it allows us to
221// * use it. Note that we would have disabled it
222// * by applying our static world regdomain by
223// * default during init, prior to calling our
224// * regulatory_hint().
225// */
226// if (!(reg_rule->flags &
227// NL80211_RRF_NO_IBSS))
228// ch->flags &=
229// ~IEEE80211_CHAN_NO_IBSS;
230// if (!(reg_rule->flags &
231// NL80211_RRF_PASSIVE_SCAN))
232// ch->flags &=
233// ~IEEE80211_CHAN_PASSIVE_SCAN;
234// } else {
235// if (ch->beacon_found)
236// ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
237// IEEE80211_CHAN_PASSIVE_SCAN);
238// }
239// }
240// }
241//
242//}
243//
244///* Allows active scan scan on Ch 12 and 13 */
245//static void
246//ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
247// enum nl80211_reg_initiator initiator)
248//{
249// struct ieee80211_supported_band *sband;
250// struct net80211_channel *ch;
251// const struct ieee80211_reg_rule *reg_rule;
252// u32 bandwidth = 0;
253// int r;
254//
255// sband = wiphy->bands[NET80211_BAND_2GHZ];
256//
257// /*
258// * If no country IE has been received always enable active scan
259// * on these channels. This is only done for specific regulatory SKUs
260// */
261// if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
262// ch = &sband->channels[11]; /* CH 12 */
263// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
264// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
265// ch = &sband->channels[12]; /* CH 13 */
266// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
267// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
268// return;
269// }
270//
271// /*
272// * If a country IE has been received check its rule for this
273// * channel first before enabling active scan. The passive scan
274// * would have been enforced by the initial processing of our
275// * custom regulatory domain.
276// */
277//
278// ch = &sband->channels[11]; /* CH 12 */
279// r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
280// if (!r) {
281// if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
282// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
283// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
284// }
285//
286// ch = &sband->channels[12]; /* CH 13 */
287// r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
288// if (!r) {
289// if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
290// if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
291// ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
292// }
293//}
294//
295///* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
296//static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
297//{
298// struct ieee80211_supported_band *sband;
299// struct net80211_channel *ch;
300// unsigned int i;
301//
302// if (!wiphy->bands[NET80211_BAND_5GHZ])
303// return;
304//
305// sband = wiphy->bands[NET80211_BAND_5GHZ];
306//
307// for (i = 0; i < sband->n_channels; i++) {
308// ch = &sband->channels[i];
309// if (!ath_is_radar_freq(ch->center_freq))
310// continue;
311// /* We always enable radar detection/DFS on this
312// * frequency range. Additionally we also apply on
313// * this frequency range:
314// * - If STA mode does not yet have DFS supports disable
315// * active scanning
316// * - If adhoc mode does not support DFS yet then
317// * disable adhoc in the frequency.
318// * - If AP mode does not yet support radar detection/DFS
319// * do not allow AP mode
320// */
321// if (!(ch->flags & IEEE80211_CHAN_DISABLED))
322// ch->flags |= IEEE80211_CHAN_RADAR |
323// IEEE80211_CHAN_NO_IBSS |
324// IEEE80211_CHAN_PASSIVE_SCAN;
325// }
326//}
327//
328//static void ath_reg_apply_world_flags(struct wiphy *wiphy,
329// enum nl80211_reg_initiator initiator,
330// struct ath_regulatory *reg)
331//{
332// switch (reg->regpair->regDmnEnum) {
333// case 0x60:
334// case 0x63:
335// case 0x66:
336// case 0x67:
337// case 0x6C:
338// ath_reg_apply_beaconing_flags(wiphy, initiator);
339// break;
340// case 0x68:
341// ath_reg_apply_beaconing_flags(wiphy, initiator);
342// ath_reg_apply_active_scan_flags(wiphy, initiator);
343// break;
344// }
345//}
346//
347//int ath_reg_notifier_apply(struct wiphy *wiphy,
348// struct regulatory_request *request,
349// struct ath_regulatory *reg)
350//{
351// /* We always apply this */
352// ath_reg_apply_radar_flags(wiphy);
353//
354// /*
355// * This would happen when we have sent a custom regulatory request
356// * a world regulatory domain and the scheduler hasn't yet processed
357// * any pending requests in the queue.
358// */
359// if (!request)
360// return 0;
361//
362// switch (request->initiator) {
363// case NL80211_REGDOM_SET_BY_DRIVER:
364// case NL80211_REGDOM_SET_BY_CORE:
365// case NL80211_REGDOM_SET_BY_USER:
366// break;
367// case NL80211_REGDOM_SET_BY_COUNTRY_IE:
368// if (ath_is_world_regd(reg))
369// ath_reg_apply_world_flags(wiphy, request->initiator,
370// reg);
371// break;
372// }
373//
374// return 0;
375//}
376//
377//static int ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
378//{
379// u16 rd = ath_regd_get_eepromRD(reg);
380// int i;
381//
382// if (rd & COUNTRY_ERD_FLAG) {
383// /* EEPROM value is a country code */
384// u16 cc = rd & ~COUNTRY_ERD_FLAG;
385// DBG2(
386// "ath: EEPROM indicates we should expect "
387// "a country code\n");
388// for (i = 0; i < ARRAY_SIZE(allCountries); i++)
389// if (allCountries[i].countryCode == cc)
390// return 1;
391// } else {
392// /* EEPROM value is a regpair value */
393// if (rd != CTRY_DEFAULT)
394// DBG2("ath: EEPROM indicates we "
395// "should expect a direct regpair map\n");
396// for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
397// if (regDomainPairs[i].regDmnEnum == rd)
398// return 1;
399// }
400// DBG(
401// "ath: invalid regulatory domain/country code 0x%x\n", rd);
402// return 0;
403//}
404//
405///* EEPROM country code to regpair mapping */
406//static struct country_code_to_enum_rd*
407//ath_regd_find_country(u16 countryCode)
408//{
409// int i;
410//
411// for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
412// if (allCountries[i].countryCode == countryCode)
413// return &allCountries[i];
414// }
415// return NULL;
416//}
417//
418///* EEPROM rd code to regpair mapping */
419//static struct country_code_to_enum_rd*
420//ath_regd_find_country_by_rd(int regdmn)
421//{
422// int i;
423//
424// for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
425// if (allCountries[i].regDmnEnum == regdmn)
426// return &allCountries[i];
427// }
428// return NULL;
429//}
430//
431///* Returns the map of the EEPROM set RD to a country code */
432//static u16 ath_regd_get_default_country(u16 rd)
433//{
434// if (rd & COUNTRY_ERD_FLAG) {
435// struct country_code_to_enum_rd *country = NULL;
436// u16 cc = rd & ~COUNTRY_ERD_FLAG;
437//
438// country = ath_regd_find_country(cc);
439// if (country != NULL)
440// return cc;
441// }
442//
443// return CTRY_DEFAULT;
444//}
445//
446//static struct reg_dmn_pair_mapping*
447//ath_get_regpair(int regdmn)
448//{
449// int i;
450//
451// if (regdmn == NO_ENUMRD)
452// return NULL;
453// for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
454// if (regDomainPairs[i].regDmnEnum == regdmn)
455// return &regDomainPairs[i];
456// }
457// return NULL;
458//}
459//
460//static int
461//ath_regd_init_wiphy(struct ath_regulatory *reg,
462// struct wiphy *wiphy,
463// int (*reg_notifier)(struct wiphy *wiphy,
464// struct regulatory_request *request))
465//{
466// const struct ieee80211_regdomain *regd;
467//
468// wiphy->reg_notifier = reg_notifier;
469// wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
470//
471// if (ath_is_world_regd(reg)) {
472// /*
473// * Anything applied here (prior to wiphy registration) gets
474// * saved on the wiphy orig_* parameters
475// */
476// regd = ath_world_regdomain(reg);
477// wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
478// } else {
479// /*
480// * This gets applied in the case of the absence of CRDA,
481// * it's our own custom world regulatory domain, similar to
482// * cfg80211's but we enable passive scanning.
483// */
484// regd = ath_default_world_regdomain();
485// }
486// wiphy_apply_custom_regulatory(wiphy, regd);
487// ath_reg_apply_radar_flags(wiphy);
488// ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
489// return 0;
490//}
491//
492///*
493// * Some users have reported their EEPROM programmed with
494// * 0x8000 set, this is not a supported regulatory domain
495// * but since we have more than one user with it we need
496// * a solution for them. We default to 0x64, which is the
497// * default Atheros world regulatory domain.
498// */
499//static void ath_regd_sanitize(struct ath_regulatory *reg)
500//{
501// if (reg->current_rd != COUNTRY_ERD_FLAG)
502// return;
503// DBG2("ath: EEPROM regdomain sanitized\n");
504// reg->current_rd = 0x64;
505//}
506//
507//int
508//ath_regd_init(struct ath_regulatory *reg,
509// struct wiphy *wiphy,
510// int (*reg_notifier)(struct wiphy *wiphy,
511// struct regulatory_request *request))
512//{
513// struct country_code_to_enum_rd *country = NULL;
514// u16 regdmn;
515//
516// if (!reg)
517// return -EINVAL;
518//
519// ath_regd_sanitize(reg);
520//
521// DBG2("ath: EEPROM regdomain: 0x%0x\n", reg->current_rd);
522//
523// if (!ath_regd_is_eeprom_valid(reg)) {
524// DBG("ath: Invalid EEPROM contents\n");
525// return -EINVAL;
526// }
527//
528// regdmn = ath_regd_get_eepromRD(reg);
529// reg->country_code = ath_regd_get_default_country(regdmn);
530//
531// if (reg->country_code == CTRY_DEFAULT &&
532// regdmn == CTRY_DEFAULT) {
533// DBG2("ath: EEPROM indicates default "
534// "country code should be used\n");
535// reg->country_code = CTRY_UNITED_STATES;
536// }
537//
538// if (reg->country_code == CTRY_DEFAULT) {
539// country = NULL;
540// } else {
541// DBG2("ath: doing EEPROM country->regdmn "
542// "map search\n");
543// country = ath_regd_find_country(reg->country_code);
544// if (country == NULL) {
545// DBG(
546// "ath: no valid country maps found for "
547// "country code: 0x%0x\n",
548// reg->country_code);
549// return -EINVAL;
550// } else {
551// regdmn = country->regDmnEnum;
552// DBG2("ath: country maps to "
553// "regdmn code: 0x%0x\n",
554// regdmn);
555// }
556// }
557//
558// reg->regpair = ath_get_regpair(regdmn);
559//
560// if (!reg->regpair) {
561// DBG("ath: "
562// "No regulatory domain pair found, cannot continue\n");
563// return -EINVAL;
564// }
565//
566// if (!country)
567// country = ath_regd_find_country_by_rd(regdmn);
568//
569// if (country) {
570// reg->alpha2[0] = country->isoName[0];
571// reg->alpha2[1] = country->isoName[1];
572// } else {
573// reg->alpha2[0] = '0';
574// reg->alpha2[1] = '0';
575// }
576//
577// DBG2("ath: Country alpha2 being used: %c%c\n",
578// reg->alpha2[0], reg->alpha2[1]);
579// DBG2("ath: Regpair used: 0x%0x\n",
580// reg->regpair->regDmnEnum);
581//
582// ath_regd_init_wiphy(reg, wiphy, reg_notifier);
583// return 0;
584//}
585
587 int band)
588{
589 /* TODO Cottsay: reg */
590// if (!reg->regpair ||
591// (reg->country_code == CTRY_DEFAULT &&
592// is_wwr_sku(ath_regd_get_eepromRD(reg)))) {
593// return SD_NO_CTL;
594// }
595
596 switch (band) {
598 return reg->regpair->reg_2ghz_ctl;
600 return reg->regpair->reg_5ghz_ctl;
601 default:
602 return NO_CTL;
603 }
604}
#define NO_CTL
Definition eeprom.h:69
u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, int band)
Definition ath_regd.c:586
#define NET80211_BAND_2GHZ
The 2.4 GHz ISM band, unlicensed in most countries.
Definition net80211.h:45
#define NET80211_BAND_5GHZ
The band from 4.9 GHz to 5.7 GHz, which tends to be more restricted.
Definition net80211.h:47
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
static unsigned int unsigned int reg
Definition myson.h:162
#define u32
Definition vga.h:21