This source file includes following definitions.
- dmi_entry_free
- to_entry
- to_attr
- dmi_sysfs_attr_show
- find_dmi_entry_helper
- find_dmi_entry
- dmi_entry_length
- dmi_entry_attr_show_helper
- dmi_entry_attr_show
- read_sel_8bit_indexed_io
- read_sel_2x8bit_indexed_io
- read_sel_16bit_indexed_io
- dmi_sel_raw_read_io
- dmi_sel_raw_read_phys32
- dmi_sel_raw_read_helper
- dmi_sel_raw_read
- dmi_system_event_log
- dmi_sysfs_entry_length
- dmi_sysfs_entry_handle
- dmi_sysfs_entry_type
- dmi_sysfs_entry_instance
- dmi_sysfs_entry_position
- dmi_entry_raw_read_helper
- dmi_entry_raw_read
- dmi_sysfs_entry_release
- dmi_sysfs_register_handle
- cleanup_entry_list
- dmi_sysfs_init
- dmi_sysfs_exit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 #include <linux/kernel.h>
  20 #include <linux/init.h>
  21 #include <linux/module.h>
  22 #include <linux/types.h>
  23 #include <linux/kobject.h>
  24 #include <linux/dmi.h>
  25 #include <linux/capability.h>
  26 #include <linux/slab.h>
  27 #include <linux/list.h>
  28 #include <linux/io.h>
  29 #include <asm/dmi.h>
  30 
  31 #define MAX_ENTRY_TYPE 255 
  32 
  33 
  34 struct dmi_sysfs_entry {
  35         struct dmi_header dh;
  36         struct kobject kobj;
  37         int instance;
  38         int position;
  39         struct list_head list;
  40         struct kobject *child;
  41 };
  42 
  43 
  44 
  45 
  46 
  47 
  48 static LIST_HEAD(entry_list);
  49 static DEFINE_SPINLOCK(entry_list_lock);
  50 
  51 
  52 struct dmi_sysfs_attribute {
  53         struct attribute attr;
  54         ssize_t (*show)(struct dmi_sysfs_entry *entry, char *buf);
  55 };
  56 
  57 #define DMI_SYSFS_ATTR(_entry, _name) \
  58 struct dmi_sysfs_attribute dmi_sysfs_attr_##_entry##_##_name = { \
  59         .attr = {.name = __stringify(_name), .mode = 0400}, \
  60         .show = dmi_sysfs_##_entry##_##_name, \
  61 }
  62 
  63 
  64 
  65 
  66 
  67 struct dmi_sysfs_mapped_attribute {
  68         struct attribute attr;
  69         ssize_t (*show)(struct dmi_sysfs_entry *entry,
  70                         const struct dmi_header *dh,
  71                         char *buf);
  72 };
  73 
  74 #define DMI_SYSFS_MAPPED_ATTR(_entry, _name) \
  75 struct dmi_sysfs_mapped_attribute dmi_sysfs_attr_##_entry##_##_name = { \
  76         .attr = {.name = __stringify(_name), .mode = 0400}, \
  77         .show = dmi_sysfs_##_entry##_##_name, \
  78 }
  79 
  80 
  81 
  82 
  83 static void dmi_entry_free(struct kobject *kobj)
  84 {
  85         kfree(kobj);
  86 }
  87 
  88 static struct dmi_sysfs_entry *to_entry(struct kobject *kobj)
  89 {
  90         return container_of(kobj, struct dmi_sysfs_entry, kobj);
  91 }
  92 
  93 static struct dmi_sysfs_attribute *to_attr(struct attribute *attr)
  94 {
  95         return container_of(attr, struct dmi_sysfs_attribute, attr);
  96 }
  97 
  98 static ssize_t dmi_sysfs_attr_show(struct kobject *kobj,
  99                                    struct attribute *_attr, char *buf)
 100 {
 101         struct dmi_sysfs_entry *entry = to_entry(kobj);
 102         struct dmi_sysfs_attribute *attr = to_attr(_attr);
 103 
 104         
 105         if (!capable(CAP_SYS_ADMIN))
 106                 return -EACCES;
 107 
 108         return attr->show(entry, buf);
 109 }
 110 
 111 static const struct sysfs_ops dmi_sysfs_attr_ops = {
 112         .show = dmi_sysfs_attr_show,
 113 };
 114 
 115 typedef ssize_t (*dmi_callback)(struct dmi_sysfs_entry *,
 116                                 const struct dmi_header *dh, void *);
 117 
 118 struct find_dmi_data {
 119         struct dmi_sysfs_entry  *entry;
 120         dmi_callback            callback;
 121         void                    *private;
 122         int                     instance_countdown;
 123         ssize_t                 ret;
 124 };
 125 
 126 static void find_dmi_entry_helper(const struct dmi_header *dh,
 127                                   void *_data)
 128 {
 129         struct find_dmi_data *data = _data;
 130         struct dmi_sysfs_entry *entry = data->entry;
 131 
 132         
 133         if (dh->type != entry->dh.type)
 134                 return;
 135 
 136         if (data->instance_countdown != 0) {
 137                 
 138                 data->instance_countdown--;
 139                 return;
 140         }
 141 
 142         
 143 
 144 
 145 
 146         data->instance_countdown--;
 147 
 148         
 149         data->ret = data->callback(entry, dh, data->private);
 150 }
 151 
 152 
 153 struct dmi_read_state {
 154         char *buf;
 155         loff_t pos;
 156         size_t count;
 157 };
 158 
 159 static ssize_t find_dmi_entry(struct dmi_sysfs_entry *entry,
 160                               dmi_callback callback, void *private)
 161 {
 162         struct find_dmi_data data = {
 163                 .entry = entry,
 164                 .callback = callback,
 165                 .private = private,
 166                 .instance_countdown = entry->instance,
 167                 .ret = -EIO,  
 168         };
 169         int ret;
 170 
 171         ret = dmi_walk(find_dmi_entry_helper, &data);
 172         
 173         if (ret)
 174                 return -EINVAL;
 175         return data.ret;
 176 }
 177 
 178 
 179 
 180 
 181 
 182 
 183 static size_t dmi_entry_length(const struct dmi_header *dh)
 184 {
 185         const char *p = (const char *)dh;
 186 
 187         p += dh->length;
 188 
 189         while (p[0] || p[1])
 190                 p++;
 191 
 192         return 2 + p - (const char *)dh;
 193 }
 194 
 195 
 196 
 197 
 198 struct dmi_entry_attr_show_data {
 199         struct attribute *attr;
 200         char *buf;
 201 };
 202 
 203 static ssize_t dmi_entry_attr_show_helper(struct dmi_sysfs_entry *entry,
 204                                           const struct dmi_header *dh,
 205                                           void *_data)
 206 {
 207         struct dmi_entry_attr_show_data *data = _data;
 208         struct dmi_sysfs_mapped_attribute *attr;
 209 
 210         attr = container_of(data->attr,
 211                             struct dmi_sysfs_mapped_attribute, attr);
 212         return attr->show(entry, dh, data->buf);
 213 }
 214 
 215 static ssize_t dmi_entry_attr_show(struct kobject *kobj,
 216                                    struct attribute *attr,
 217                                    char *buf)
 218 {
 219         struct dmi_entry_attr_show_data data = {
 220                 .attr = attr,
 221                 .buf  = buf,
 222         };
 223         
 224 
 225         return find_dmi_entry(to_entry(kobj->parent),
 226                               dmi_entry_attr_show_helper, &data);
 227 }
 228 
 229 static const struct sysfs_ops dmi_sysfs_specialize_attr_ops = {
 230         .show = dmi_entry_attr_show,
 231 };
 232 
 233 
 234 
 235 
 236 
 237 
 238 
 239 #define DMI_SEL_ACCESS_METHOD_IO8       0x00
 240 #define DMI_SEL_ACCESS_METHOD_IO2x8     0x01
 241 #define DMI_SEL_ACCESS_METHOD_IO16      0x02
 242 #define DMI_SEL_ACCESS_METHOD_PHYS32    0x03
 243 #define DMI_SEL_ACCESS_METHOD_GPNV      0x04
 244 
 245 struct dmi_system_event_log {
 246         struct dmi_header header;
 247         u16     area_length;
 248         u16     header_start_offset;
 249         u16     data_start_offset;
 250         u8      access_method;
 251         u8      status;
 252         u32     change_token;
 253         union {
 254                 struct {
 255                         u16 index_addr;
 256                         u16 data_addr;
 257                 } io;
 258                 u32     phys_addr32;
 259                 u16     gpnv_handle;
 260                 u32     access_method_address;
 261         };
 262         u8      header_format;
 263         u8      type_descriptors_supported_count;
 264         u8      per_log_type_descriptor_length;
 265         u8      supported_log_type_descriptos[0];
 266 } __packed;
 267 
 268 #define DMI_SYSFS_SEL_FIELD(_field) \
 269 static ssize_t dmi_sysfs_sel_##_field(struct dmi_sysfs_entry *entry, \
 270                                       const struct dmi_header *dh, \
 271                                       char *buf) \
 272 { \
 273         struct dmi_system_event_log sel; \
 274         if (sizeof(sel) > dmi_entry_length(dh)) \
 275                 return -EIO; \
 276         memcpy(&sel, dh, sizeof(sel)); \
 277         return sprintf(buf, "%u\n", sel._field); \
 278 } \
 279 static DMI_SYSFS_MAPPED_ATTR(sel, _field)
 280 
 281 DMI_SYSFS_SEL_FIELD(area_length);
 282 DMI_SYSFS_SEL_FIELD(header_start_offset);
 283 DMI_SYSFS_SEL_FIELD(data_start_offset);
 284 DMI_SYSFS_SEL_FIELD(access_method);
 285 DMI_SYSFS_SEL_FIELD(status);
 286 DMI_SYSFS_SEL_FIELD(change_token);
 287 DMI_SYSFS_SEL_FIELD(access_method_address);
 288 DMI_SYSFS_SEL_FIELD(header_format);
 289 DMI_SYSFS_SEL_FIELD(type_descriptors_supported_count);
 290 DMI_SYSFS_SEL_FIELD(per_log_type_descriptor_length);
 291 
 292 static struct attribute *dmi_sysfs_sel_attrs[] = {
 293         &dmi_sysfs_attr_sel_area_length.attr,
 294         &dmi_sysfs_attr_sel_header_start_offset.attr,
 295         &dmi_sysfs_attr_sel_data_start_offset.attr,
 296         &dmi_sysfs_attr_sel_access_method.attr,
 297         &dmi_sysfs_attr_sel_status.attr,
 298         &dmi_sysfs_attr_sel_change_token.attr,
 299         &dmi_sysfs_attr_sel_access_method_address.attr,
 300         &dmi_sysfs_attr_sel_header_format.attr,
 301         &dmi_sysfs_attr_sel_type_descriptors_supported_count.attr,
 302         &dmi_sysfs_attr_sel_per_log_type_descriptor_length.attr,
 303         NULL,
 304 };
 305 
 306 
 307 static struct kobj_type dmi_system_event_log_ktype = {
 308         .release = dmi_entry_free,
 309         .sysfs_ops = &dmi_sysfs_specialize_attr_ops,
 310         .default_attrs = dmi_sysfs_sel_attrs,
 311 };
 312 
 313 typedef u8 (*sel_io_reader)(const struct dmi_system_event_log *sel,
 314                             loff_t offset);
 315 
 316 static DEFINE_MUTEX(io_port_lock);
 317 
 318 static u8 read_sel_8bit_indexed_io(const struct dmi_system_event_log *sel,
 319                                    loff_t offset)
 320 {
 321         u8 ret;
 322 
 323         mutex_lock(&io_port_lock);
 324         outb((u8)offset, sel->io.index_addr);
 325         ret = inb(sel->io.data_addr);
 326         mutex_unlock(&io_port_lock);
 327         return ret;
 328 }
 329 
 330 static u8 read_sel_2x8bit_indexed_io(const struct dmi_system_event_log *sel,
 331                                      loff_t offset)
 332 {
 333         u8 ret;
 334 
 335         mutex_lock(&io_port_lock);
 336         outb((u8)offset, sel->io.index_addr);
 337         outb((u8)(offset >> 8), sel->io.index_addr + 1);
 338         ret = inb(sel->io.data_addr);
 339         mutex_unlock(&io_port_lock);
 340         return ret;
 341 }
 342 
 343 static u8 read_sel_16bit_indexed_io(const struct dmi_system_event_log *sel,
 344                                     loff_t offset)
 345 {
 346         u8 ret;
 347 
 348         mutex_lock(&io_port_lock);
 349         outw((u16)offset, sel->io.index_addr);
 350         ret = inb(sel->io.data_addr);
 351         mutex_unlock(&io_port_lock);
 352         return ret;
 353 }
 354 
 355 static sel_io_reader sel_io_readers[] = {
 356         [DMI_SEL_ACCESS_METHOD_IO8]     = read_sel_8bit_indexed_io,
 357         [DMI_SEL_ACCESS_METHOD_IO2x8]   = read_sel_2x8bit_indexed_io,
 358         [DMI_SEL_ACCESS_METHOD_IO16]    = read_sel_16bit_indexed_io,
 359 };
 360 
 361 static ssize_t dmi_sel_raw_read_io(struct dmi_sysfs_entry *entry,
 362                                    const struct dmi_system_event_log *sel,
 363                                    char *buf, loff_t pos, size_t count)
 364 {
 365         ssize_t wrote = 0;
 366 
 367         sel_io_reader io_reader = sel_io_readers[sel->access_method];
 368 
 369         while (count && pos < sel->area_length) {
 370                 count--;
 371                 *(buf++) = io_reader(sel, pos++);
 372                 wrote++;
 373         }
 374 
 375         return wrote;
 376 }
 377 
 378 static ssize_t dmi_sel_raw_read_phys32(struct dmi_sysfs_entry *entry,
 379                                        const struct dmi_system_event_log *sel,
 380                                        char *buf, loff_t pos, size_t count)
 381 {
 382         u8 __iomem *mapped;
 383         ssize_t wrote = 0;
 384 
 385         mapped = dmi_remap(sel->access_method_address, sel->area_length);
 386         if (!mapped)
 387                 return -EIO;
 388 
 389         while (count && pos < sel->area_length) {
 390                 count--;
 391                 *(buf++) = readb(mapped + pos++);
 392                 wrote++;
 393         }
 394 
 395         dmi_unmap(mapped);
 396         return wrote;
 397 }
 398 
 399 static ssize_t dmi_sel_raw_read_helper(struct dmi_sysfs_entry *entry,
 400                                        const struct dmi_header *dh,
 401                                        void *_state)
 402 {
 403         struct dmi_read_state *state = _state;
 404         struct dmi_system_event_log sel;
 405 
 406         if (sizeof(sel) > dmi_entry_length(dh))
 407                 return -EIO;
 408 
 409         memcpy(&sel, dh, sizeof(sel));
 410 
 411         switch (sel.access_method) {
 412         case DMI_SEL_ACCESS_METHOD_IO8:
 413         case DMI_SEL_ACCESS_METHOD_IO2x8:
 414         case DMI_SEL_ACCESS_METHOD_IO16:
 415                 return dmi_sel_raw_read_io(entry, &sel, state->buf,
 416                                            state->pos, state->count);
 417         case DMI_SEL_ACCESS_METHOD_PHYS32:
 418                 return dmi_sel_raw_read_phys32(entry, &sel, state->buf,
 419                                                state->pos, state->count);
 420         case DMI_SEL_ACCESS_METHOD_GPNV:
 421                 pr_info("dmi-sysfs: GPNV support missing.\n");
 422                 return -EIO;
 423         default:
 424                 pr_info("dmi-sysfs: Unknown access method %02x\n",
 425                         sel.access_method);
 426                 return -EIO;
 427         }
 428 }
 429 
 430 static ssize_t dmi_sel_raw_read(struct file *filp, struct kobject *kobj,
 431                                 struct bin_attribute *bin_attr,
 432                                 char *buf, loff_t pos, size_t count)
 433 {
 434         struct dmi_sysfs_entry *entry = to_entry(kobj->parent);
 435         struct dmi_read_state state = {
 436                 .buf = buf,
 437                 .pos = pos,
 438                 .count = count,
 439         };
 440 
 441         return find_dmi_entry(entry, dmi_sel_raw_read_helper, &state);
 442 }
 443 
 444 static struct bin_attribute dmi_sel_raw_attr = {
 445         .attr = {.name = "raw_event_log", .mode = 0400},
 446         .read = dmi_sel_raw_read,
 447 };
 448 
 449 static int dmi_system_event_log(struct dmi_sysfs_entry *entry)
 450 {
 451         int ret;
 452 
 453         entry->child = kzalloc(sizeof(*entry->child), GFP_KERNEL);
 454         if (!entry->child)
 455                 return -ENOMEM;
 456         ret = kobject_init_and_add(entry->child,
 457                                    &dmi_system_event_log_ktype,
 458                                    &entry->kobj,
 459                                    "system_event_log");
 460         if (ret)
 461                 goto out_free;
 462 
 463         ret = sysfs_create_bin_file(entry->child, &dmi_sel_raw_attr);
 464         if (ret)
 465                 goto out_del;
 466 
 467         return 0;
 468 
 469 out_del:
 470         kobject_del(entry->child);
 471 out_free:
 472         kfree(entry->child);
 473         return ret;
 474 }
 475 
 476 
 477 
 478 
 479 
 480 static ssize_t dmi_sysfs_entry_length(struct dmi_sysfs_entry *entry, char *buf)
 481 {
 482         return sprintf(buf, "%d\n", entry->dh.length);
 483 }
 484 
 485 static ssize_t dmi_sysfs_entry_handle(struct dmi_sysfs_entry *entry, char *buf)
 486 {
 487         return sprintf(buf, "%d\n", entry->dh.handle);
 488 }
 489 
 490 static ssize_t dmi_sysfs_entry_type(struct dmi_sysfs_entry *entry, char *buf)
 491 {
 492         return sprintf(buf, "%d\n", entry->dh.type);
 493 }
 494 
 495 static ssize_t dmi_sysfs_entry_instance(struct dmi_sysfs_entry *entry,
 496                                         char *buf)
 497 {
 498         return sprintf(buf, "%d\n", entry->instance);
 499 }
 500 
 501 static ssize_t dmi_sysfs_entry_position(struct dmi_sysfs_entry *entry,
 502                                         char *buf)
 503 {
 504         return sprintf(buf, "%d\n", entry->position);
 505 }
 506 
 507 static DMI_SYSFS_ATTR(entry, length);
 508 static DMI_SYSFS_ATTR(entry, handle);
 509 static DMI_SYSFS_ATTR(entry, type);
 510 static DMI_SYSFS_ATTR(entry, instance);
 511 static DMI_SYSFS_ATTR(entry, position);
 512 
 513 static struct attribute *dmi_sysfs_entry_attrs[] = {
 514         &dmi_sysfs_attr_entry_length.attr,
 515         &dmi_sysfs_attr_entry_handle.attr,
 516         &dmi_sysfs_attr_entry_type.attr,
 517         &dmi_sysfs_attr_entry_instance.attr,
 518         &dmi_sysfs_attr_entry_position.attr,
 519         NULL,
 520 };
 521 
 522 static ssize_t dmi_entry_raw_read_helper(struct dmi_sysfs_entry *entry,
 523                                          const struct dmi_header *dh,
 524                                          void *_state)
 525 {
 526         struct dmi_read_state *state = _state;
 527         size_t entry_length;
 528 
 529         entry_length = dmi_entry_length(dh);
 530 
 531         return memory_read_from_buffer(state->buf, state->count,
 532                                        &state->pos, dh, entry_length);
 533 }
 534 
 535 static ssize_t dmi_entry_raw_read(struct file *filp,
 536                                   struct kobject *kobj,
 537                                   struct bin_attribute *bin_attr,
 538                                   char *buf, loff_t pos, size_t count)
 539 {
 540         struct dmi_sysfs_entry *entry = to_entry(kobj);
 541         struct dmi_read_state state = {
 542                 .buf = buf,
 543                 .pos = pos,
 544                 .count = count,
 545         };
 546 
 547         return find_dmi_entry(entry, dmi_entry_raw_read_helper, &state);
 548 }
 549 
 550 static const struct bin_attribute dmi_entry_raw_attr = {
 551         .attr = {.name = "raw", .mode = 0400},
 552         .read = dmi_entry_raw_read,
 553 };
 554 
 555 static void dmi_sysfs_entry_release(struct kobject *kobj)
 556 {
 557         struct dmi_sysfs_entry *entry = to_entry(kobj);
 558 
 559         spin_lock(&entry_list_lock);
 560         list_del(&entry->list);
 561         spin_unlock(&entry_list_lock);
 562         kfree(entry);
 563 }
 564 
 565 static struct kobj_type dmi_sysfs_entry_ktype = {
 566         .release = dmi_sysfs_entry_release,
 567         .sysfs_ops = &dmi_sysfs_attr_ops,
 568         .default_attrs = dmi_sysfs_entry_attrs,
 569 };
 570 
 571 static struct kset *dmi_kset;
 572 
 573 
 574 static int __initdata instance_counts[MAX_ENTRY_TYPE + 1];
 575 
 576 
 577 static int __initdata position_count;
 578 
 579 static void __init dmi_sysfs_register_handle(const struct dmi_header *dh,
 580                                              void *_ret)
 581 {
 582         struct dmi_sysfs_entry *entry;
 583         int *ret = _ret;
 584 
 585         
 586         if (*ret)
 587                 return;
 588 
 589         
 590         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 591         if (!entry) {
 592                 *ret = -ENOMEM;
 593                 return;
 594         }
 595 
 596         
 597         memcpy(&entry->dh, dh, sizeof(*dh));
 598         entry->instance = instance_counts[dh->type]++;
 599         entry->position = position_count++;
 600 
 601         entry->kobj.kset = dmi_kset;
 602         *ret = kobject_init_and_add(&entry->kobj, &dmi_sysfs_entry_ktype, NULL,
 603                                     "%d-%d", dh->type, entry->instance);
 604 
 605         if (*ret) {
 606                 kfree(entry);
 607                 return;
 608         }
 609 
 610         
 611         spin_lock(&entry_list_lock);
 612         list_add_tail(&entry->list, &entry_list);
 613         spin_unlock(&entry_list_lock);
 614 
 615         
 616         switch (dh->type) {
 617         case DMI_ENTRY_SYSTEM_EVENT_LOG:
 618                 *ret = dmi_system_event_log(entry);
 619                 break;
 620         default:
 621                 
 622                 break;
 623         }
 624         if (*ret)
 625                 goto out_err;
 626 
 627         
 628         *ret = sysfs_create_bin_file(&entry->kobj, &dmi_entry_raw_attr);
 629         if (*ret)
 630                 goto out_err;
 631 
 632         return;
 633 out_err:
 634         kobject_put(entry->child);
 635         kobject_put(&entry->kobj);
 636         return;
 637 }
 638 
 639 static void cleanup_entry_list(void)
 640 {
 641         struct dmi_sysfs_entry *entry, *next;
 642 
 643         
 644         list_for_each_entry_safe(entry, next, &entry_list, list) {
 645                 kobject_put(entry->child);
 646                 kobject_put(&entry->kobj);
 647         }
 648 }
 649 
 650 static int __init dmi_sysfs_init(void)
 651 {
 652         int error;
 653         int val;
 654 
 655         if (!dmi_kobj) {
 656                 pr_debug("dmi-sysfs: dmi entry is absent.\n");
 657                 error = -ENODATA;
 658                 goto err;
 659         }
 660 
 661         dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj);
 662         if (!dmi_kset) {
 663                 error = -ENOMEM;
 664                 goto err;
 665         }
 666 
 667         val = 0;
 668         error = dmi_walk(dmi_sysfs_register_handle, &val);
 669         if (error)
 670                 goto err;
 671         if (val) {
 672                 error = val;
 673                 goto err;
 674         }
 675 
 676         pr_debug("dmi-sysfs: loaded.\n");
 677 
 678         return 0;
 679 err:
 680         cleanup_entry_list();
 681         kset_unregister(dmi_kset);
 682         return error;
 683 }
 684 
 685 
 686 static void __exit dmi_sysfs_exit(void)
 687 {
 688         pr_debug("dmi-sysfs: unloading.\n");
 689         cleanup_entry_list();
 690         kset_unregister(dmi_kset);
 691 }
 692 
 693 module_init(dmi_sysfs_init);
 694 module_exit(dmi_sysfs_exit);
 695 
 696 MODULE_AUTHOR("Mike Waychison <mikew@google.com>");
 697 MODULE_DESCRIPTION("DMI sysfs support");
 698 MODULE_LICENSE("GPL");